打包包含C共享库的Python库的最佳方式是什么?
我写了一个库,主要功能是用C语言实现的,因为速度非常重要。然后我在它周围加了一层薄薄的Python代码,主要是为了处理一些ctypes
相关的问题。
现在我想把它打包,想知道该怎么做比较好。我的代码需要和一个共享库进行交互。我有一个Makefile,可以用来编译C代码并生成.so
文件,但我不太清楚如何通过distutils来编译这个文件。我是不是应该用subprocess
调用make
,并重写install
命令?如果是这样的话,install
适合放这个吗,还是build
更合适呢?
更新:我想说明一下,这不是一个Python扩展。也就是说,这个C库里面没有任何代码是用来和Python运行时交互的。Python只是调用了一个普通的C共享库里的函数。
3 个回答
如果你按照说明书上的步骤去做,学习了如何用C语言创建Python扩展,那么你只需要像文档中提到的那样列出扩展模块就可以了。
所以,你的库的 setup.py
脚本应该是这样的:
from distutils.core import setup, Extension
setup(
name='your_python_library',
version='1.0',
ext_modules=[Extension('your_c_extension', ['your_c_extension.c'])],
)
而且 distutils
知道怎么把你的扩展编译成C语言的共享库,并且知道把它放在哪里。
当然,我对你的库没有更多的信息,所以你可能还想在 setup(...)
的调用中添加更多的参数。
我之前也遇到过类似的情况,发现这个回答很有帮助:Python setup.py 调用 makefile 不包含二进制文件。
我在我的项目的 src
文件夹里有一个 ANSI C 库。在这个 src
文件夹里有一个 Makefile,它会生成一个叫 liblsd.so
的文件,这个文件会放在我的包目录(lsd
)里。我在 setup.py 里调用这个 Makefile,然后告诉 setup 包含这个库文件,使用的是 package_data
参数。
import os.path
import subprocess
from setuptools import setup
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as f:
readme = f.read()
subprocess.call(['make', '-C', 'src'])
setup(name='LSD',
version='0.0.1',
description='Python bindings for the LSD line segment detector.',
long_description=readme,
author='Geoff Hing',
author_email='geoffhing@gmail.com',
url='https://github.com/ghing/python-lsd',
packages=['lsd'],
package_data={'lsd': ['liblsd.so']},
include_package_data=True,
classifiers=[
'Development Status :: 1 - Planning',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: C',
],
)
我建议把这个Python模块当作一个普通共享库构建的子项目来做。也就是说,可以使用automake、autoconf之类的工具来构建共享库,然后在项目里创建一个叫做python_bindings的文件夹,里面放上setup.py和你的Python模块。