【问题标题】:What is the right way to ship dynamic library *.so with python package?使用 python 包发布动态库 *.so 的正确方法是什么?
【发布时间】:2021-08-05 10:25:06
【问题描述】:

我有一个包需要 a.so,它加载 b.so 并通过 ctypes.cdll.LoadLibrary(a_so_path) 加载它。

所以我必须将它们与我的包裹一起运送。

这里有两个想法。

  1. LD_LIBRARY_PATH 设置为我的站点包

现在的问题是,如何在运行时更改 lib 加载路径,在我的模块中设置 LD_LIBRARY_PATH 将不起作用(参考 Set LD_LIBRARY_PATH before importing in python)。但它是一个包,我不能让每个用户在将LD_LIBRARY_PATH 设置为***/lib/python3.8/site-packages/mypackage/lib/ 的shell 脚本中加载python。

  1. 安装*.so到系统库

我在setup.cfg 中发现data_files 可以从站点包中分发文件(到/usr/lib 可以在哪里找到)。但不幸的是,它不支持 egg 或 wheel 包。见https://packaging.python.org/guides/distributing-packages-using-setuptools/#id55

那么,发布我的包的正确方法是什么?

【问题讨论】:

  • 我相信你想建立一个wheel
  • @chepner,我已经造了一个轮子,但是我应该把so文件放在哪里?我的包的根目录?
  • 我的印象是共享库包含在 轮子中,而 pip 会负责为您正确安装轮子。
  • 或者您是在问它们应该安装在车轮内的哪个位置?
  • 您可以在setup 函数中包含package_data 选项,以指定您要随附的文件。 setuptools.readthedocs.io/en/latest/userguide/…。您可以使用importlib.resourcespkg_resources 模块来查找包中文件的位置。

标签: python


【解决方案1】:

有问题的两种方法都行不通。我最终选择更改我的动态库的RUNPATH

使用patchelf(如果你的*.so已经有RUNPATH,则使用chrpath),将所有动态库放在一个文件夹中并运行:

find . -name "*.so" | xargs -l1 -t patchelf --set-rpath "\$ORIGIN"

动态库会在RUNPATH中搜索depends,而"\$ORIGIN"表示当前二进制路径,所以如果我们将所有*.so放在一个目录下,就会找到被依赖的*.so。 p>

然后将它们打包成轮子使用

from setuptools import setup, find_packages
setup(
    ...
    package_data={
        # If any package contains *.so, include them:
        "": ["*.so",],
    }
)

现在,一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多