Python Wheel包中分发的依赖共享库无法找到问题咨询
这个问题很常见,本质是动态链接器找不到共享库的路径——你生成的wheel把shared_lib.so放在了site-packages根目录,但默认情况下动态链接器不会搜索这个位置,而且你的extension.so编译时也没指定正确的加载路径。下面给你几个靠谱的解决方案:
方法1:调整setup.py,把共享库放入包目录并设置rpath
这是从根源解决问题的方式,让共享库和扩展的加载路径绑定:
修改setup.py配置
把shared_lib.so作为pymodule包的一部分,同时给extension.so设置rpath,让它知道去哪里找共享库:from setuptools import setup, Extension setup( name="pymodule", version="0.1.0", packages=["pymodule"], # 指定pymodule包要包含的共享库文件 package_data={ "pymodule": ["shared_lib.so"], }, # 确保打包时自动包含这些数据文件 include_package_data=True, ext_modules=[ Extension( # 推荐把扩展放在pymodule包内,路径更规整 "pymodule.extension", sources=["src/extension.cpp"], extra_objects=["path/to/shared_lib.so"], # 设置rpath为当前目录(因为扩展和共享库都在pymodule目录下) extra_link_args=["-Wl,-rpath,$ORIGIN"] ) ] )如果坚持把
extension.so放在site-packages根目录(命名为extension),那rpath要改成-Wl,-rpath,$ORIGIN/pymodule,这样动态链接器会从根目录往下找pymodule里的共享库。重新生成并安装wheel
python setup.py bdist_wheel pip install dist/pymodule-0.1.0-*.whl此时
shared_lib.so会被安装到site-packages/pymodule/,extension.so通过rpath能精准找到它。
方法2:用auditwheel修复wheel(推荐懒人方案)
如果你不想改setup.py的代码,auditwheel是专门处理Python wheel共享库依赖的工具,它会自动把共享库打包到wheel里,设置好rpath,还能生成兼容多Linux发行版的wheel:
安装auditwheel
pip install auditwheel修复现有wheel
运行命令后,修复后的wheel会放在wheelhouse/目录下:auditwheel repair pymodule.whl安装修复后的wheel
pip install wheelhouse/pymodule-0.1.0-*.whlauditwheel会自动处理所有路径问题,完全不用你操心。
不推荐的临时方案:手动设置LD_LIBRARY_PATH
虽然能解决,但不够优雅,适合临时测试:
- 运行前设置环境变量:
export LD_LIBRARY_PATH=$(python -c "import site; print(site.getsitepackages()[0])"):$LD_LIBRARY_PATH python your_script.py - 或者在Python模块里手动加载:
这个方法容易因为环境差异出问题,不建议用于生产环境。import os import sys from ctypes import CDLL # 获取site-packages目录 site_packages = next(p for p in sys.path if 'site-packages' in p) # 手动加载共享库 CDLL(os.path.join(site_packages, 'shared_lib.so')) # 再导入你的扩展 import extension
内容的提问来源于stack exchange,提问作者mcguip

