30

.so我想使用 cffi 模块为在 Linux 上嵌入并使用外部库 () 的 python 创建包。

是否有标准方法将 .so 文件包含到 python 包中?

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

我认为 Wheel 包是最好的选择 - 他们会创建平台特定的包,其中所有文件都准备好被复制,因此不需要在目标环境上构建任何东西。

4

2 回答 2

23

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

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

您可以通过通常执行以下操作来预构建外部 c++ 库:

./configure && make && make install

这将生成一个my_external_library.so文件并将其安装在适当的路径中。但是,您需要确保正确设置库路径,以便审计轮发现丢失的依赖项。

export LD_LIBRARY_PATH=/usr/local/lib

然后,您可以通过执行以下命令来构建 python 轮:

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工具。

于 2017-02-08T06:20:51.960 回答
7

Wheels 是分发 Python 包的标准方式,但是当您的扩展模块依赖于其他so的时,就会出现问题。这是因为使用了普通的 Linux 动态链接器,并且只在/usr/libor中查找/usr/local/lib。这是在安装轮子时出现的问题virtualenv

据我所知,你有三个选择:

  • 静态链接,因此“包装器”不依赖于其他任何东西;
  • 用于直接从 Pythonctypes包装;so
  • 使用 Python 代码和包装器将发行版拆分为一个轮子,以及一个单独的 RPM 或 DEB 以将其安装到其中一个/usr/lib/usr/local/lib.

如果您将依赖项作为数据文件包含在其中并安装到根 Python 环境中(尚未尝试过),则轮子可能会起作用,但是如果有人尝试将轮子安装到 virtualenv 中(尝试过)。so/lib

于 2015-06-19T15:02:12.923 回答