如何将外部库与Python Wheel包一起使用

32

我想创建一个Python包,使用cffi模块在Linux上嵌入和使用外部库(.so文件)。

有没有标准的方法将 .so 文件包含到Python包中?

此包仅在内部使用,不会发布到pypi。

我认为Wheel包是最好的选择-它们会创建平台特定的包,并准备好所有文件供复制,因此在目标环境中无需构建任何内容。


你尝试过为你的包创建轮子吗?有很大的可能性它会将所需的文件包含在其中(但我不确定)。 - Jan Vlcinsky
我尝试为该软件包构建wheel - 它包含了由cffi创建的.so文件,它链接到外部库,但不包括外部库本身。 - vvladymyrov
我想我会将.so库打包成rpm包(这样也可以让我在需要时从源代码重新编译它们)。 - vvladymyrov
2个回答

28

您可以使用auditwheel将外部库注入到Wheel中:

auditwheel repair:将这些外部共享库复制到Wheel本身中,并自动修改适当的RPATH条目,以便在运行时拾取这些库。 这实现了与静态链接类似的结果,而无需更改构建系统。 建议打包者不要捆绑,像静态链接一样,可能会涉及版权问题。

通常情况下,您可以通过执行以下命令预先构建外部c ++库:

./configure && make && make install

这将生成一个名为my_external_library.so的文件并将其安装在适当的路径中。但是,您需要确保库路径已正确设置,以便auditwheel能够发现缺失的依赖项。

export LD_LIBRARY_PATH=/usr/local/lib

您可以执行以下命令来构建 Python 轮(wheel):

python setup.py bdist_wheel

最后,您可以修复轮子,这将把my_external_library.so注入包中。

auditwheel repair my-python-wheel-1.5.2-cp35-cp35m-linux_x86_64.whl

我成功地将上述步骤应用于Python库confluent-kafka-python,该库必须依赖于librdkafka的C/C++。


注意:auditwheel仅适用于Linux。对于MacOS,请参见delocate工具。


1
谢谢你的提示。auditwheel来自pypa(Python Packaging Authority) - 他们应该知道他们在做什么 :) - vvladymyrov
有人尝试过吗?在构建针对ARM的特定轮子方面效果如何? - Cucu
auditwheel 不是用于构建轮子,而是用于使它们符合 manylinux 标准。arm 不是一个符合 manylinux 标准的平台,因此它对你没有帮助。但是,使用 setuptools 可以构建一个非 manylinux 轮子,该轮子可能链接到一些外部内容。 - webknjaz -- Слава Україні
我不得不在auditwheel命令中加入参数--plat linux_x86_64,因为默认情况下该工具会尝试将wheel标准化为manylinux(而且由于我是在Github Actions中进行操作,所使用的Docker镜像版本太新,无法正确运行manylinux)。 - Astariul

7
轮子是分发Python软件包的标准方式,但是当您有依赖其他'so'的扩展模块时会有问题。这是因为使用了正常的Linux动态链接器,它只查看'/usr/lib'或'/usr/local/lib'。在virtualenv中安装轮子时,这是一个问题。
据我所知,您有三个选择:
1.静态链接,因此“包装器”不依赖于其他任何内容;
2.使用ctypes直接从Python包装so;
3.将分发拆分为具有Python代码和包装器的轮以及单独的RPM或DEB,以将so安装到'/usr/lib'或'/usr/local/lib'中。
如果将依赖的'so'作为数据文件包含在'/lib'中并安装到根Python环境中,则轮可能有效(尚未尝试),但是如果有人尝试将轮安装到虚拟环境中,则会出现问题。

3
为什么不能将 so 文件留在 site-packages/ 包目录下? - Keto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接