我有一个依赖共享库的项目。从一开始就明确:共享库是一个纯 C 库,而不是 Python 库。为了简单起见,我创建了一个名为 pkgtest 的小型演示项目,我将引用它。
所以需要做的是:运行 Makefile 来编译库并将编译后的共享库(此处称为 libhello.so
)文件放置在可以从依赖的 Python 包中访问的位置.
到目前为止,我最好的猜测是将 makefile 作为预安装例程运行,复制 packages 目录中的 libhello.so
文件并将其添加到 package_data
参数中安装脚本。安装后,共享库将放置在 site-packages/pkgtest/
目录中,可以从模块访问。
包目录结构很简单:
pkgtest/
src/
libhello.c
libhello.h
Makefile
pkgtest/
__init__.py
hello.py
setup.py
我的 setup.py 看起来像这样:
setup.py
import subprocess
from setuptools import setup
from distutils.command.install import install as _install
class install(_install):
def run(self):
subprocess.call(['make', 'clean', '-C', 'src'])
subprocess.call(['make', '-C', 'src'])
_install.run(self)
setup(
name='pkgtest',
version='0.0.1',
author='stefan',
packages=['pkgtest'],
package_data={'pkgtest': ['libhello.so']},
cmdclass={'install': install},
)
Makefile 实际上构建库并将其复制到我的 python 包的目录中。
src/Makefile
all: libhello.so
libhello.o: libhello.c
gcc -fPIC -Wall -g -c libhello.c
libhello.so: libhello.o
gcc -shared -fPIC -o libhello.so libhello.o
cp libhello.so ../pkgtest/libhello.so
clean:
rm -f *.o *.so
所以 hello.py
实际上所做的就是加载库并调用打印一些文本的 hello
函数。但为了完整起见,我将在此处显示代码:
pkgtest/hello.py
import os
import ctypes
basedir = os.path.abspath(os.path.dirname(__file__))
libpath = os.path.join(basedir, 'libhello.so')
dll = ctypes.CDLL(libpath)
def say_hello():
dll.hello()
所以这实际上可行,但我不喜欢这种方法的是共享库位于 Python 包的目录中。我认为将它放在某种中央库目录中会更好,例如 /usr/lib/。但是对于这个,安装时需要 root 权限。是否有人对此类问题有一些经验,并愿意分享解决方案或有用的想法。会很棒。
最佳答案
您可以使用 manylinux 创建一个包含共享库并适用于(几乎)任何 Linux 发行版的 Python 包.
The goal of the manylinux project is to provide a convenient way to distribute binary Python extensions as wheels on Linux. This effort has produced PEP 513 which defines the
manylinux1_x86_64
andmanylinux1_i686
platform tags.
一般程序是:
- 在 manylinux 团队提供的其中一个 docker 容器中构建外部库和 Python 包 (参见 python-manylinux-demo)
- 运行
auditwheel repair
将您的包所依赖的外部共享库复制到 Python 轮中,相应地设置 RPATH。
参见 .travis.yml
和 build-wheels.sh
在 python-manylinux-demo
存储库中作为示例。
关于python - 如何在 Python 包中包含共享 C 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45121352/