如何在Python包中包含共享C库
我有一个项目取决于共享库。为了从头开始说明:共享库是一个纯粹的C库,而不是一个Python库。为了简单起见,我创建了一个名为pkgtest的小型演示项目,我将参考它。如何在Python包中包含共享C库
所以需要做的是:运行一个Makefile来编译库,并将编译后的共享库(在此称为libhello.so
)文件放置在某个可从取决于的Python包中访问的位置。
我最好的猜测,到目前为止是运行makefile作为一个预安装程序中,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权限。有人有这种问题的一些经验,并希望分享一个解决方案或有用的想法。会很好。
您可以创建一个包含共享库的Python包,它可以在几乎所有使用manylinux的Linux发行版上运行。
manylinux项目的目标是提供一种方便的方式将二进制Python扩展作为*分布在Linux上。这项工作产生了PEP 513,它定义了
manylinux1_x86_64
和manylinux1_i686
平台标签。
的一般程序是:
- 构建外部库和Python包内由manylinux队 提供的泊坞窗容器之一(见python-manylinux-demo)
- 运行
auditwheel repair
复制的外部您的软件包依赖的共享库放入Python滚轮,相应地设置RPATH。
参见.travis.yml
和build-wheels.sh
在python-manylinux-demo
回购的一个例子。
这看起来不错。如果我明白了,这个例子展示了如何构建一个Python C扩展并将其包含在内。正如问题中所述,目标不是构建Python C扩展,而是构建并包含纯C的共享库。我仍然无法弄清楚如何管理它。 – MrLeeh
你有没有考虑过像[conda](https://conda.io/miniconda.html)这样的软件包管理器?您可以为您的库和Python代码创建一个单独的包,并将该库指定为'meta.yaml'文件中Python代码的依赖关系。 – ostrokach
我没有想过conda,但。你是对的,这肯定是一个选择,但不是我的第一选择,因为我希望这个软件包可以通过'pip install ...'来使用。 – MrLeeh
在这种情况下,我不认为你的python包文件夹中有一个编译的库文件是一个问题。这就是[Python扩展模块](https://docs.python.org/3/extending/building.html)和[Cython](http://docs.cython.org/en/latest/index.html)模块摆放在。但也许有更好的解决方案... – ostrokach