打包预建的python扩展

时间:2019-01-06 21:12:19

标签: cmake cython

我正在开发一个C库(使用cmake作为构建系统)和一个用cython编写的相应python扩展。

构建过程由cmake进行,后者调用cython可执行文件以生成C文件。该文件被编译成python_library.so链接 针对本机library.so和其他依赖项。

该库可以正常工作,我可以将PYTHONPATH设置到构建目录,运行python和import并执行包装的python代码。

剩下的是关于如何安装/打包python模块的问题。 据我所知,创建python软件包的推荐方法是在setup.py文件中使用setuptools / distutils。

当然可以在Extension文件中定义C setup.py(可选使用cython)。但是,我希望编译由cmake处理(它涉及一些依赖库等)

因此,基本上,我想告诉python,整个包是由现有的python_library.so文件定义的。那有可能吗?

注意:这里有一个related问题。但是OP 已经已经弄清楚了如何打包扩展。

1 个答案:

答案 0 :(得分:1)

显然,这不是分发python软件包的最可靠的方法,因为它不适用于不同的操作系统,或者如果存在Python版本不匹配的话,可能会导致奇怪的结果-但这仍然是可能的。

让我们考虑以下文件夹结构:

/
|--- setup.py
|--- my_package
        |-------  __init__.py
        |-------  impl.pyx          [needed only for creation of impl.so]
        |-------  impl-XXX.so       [created via "cythonize -i impl.pyx"]

具有以下内容:

__ init __。py:

from .impl import foo

impl.pyx:

def foo():
    print("I'm foo from impl")

setup.py:

from setuptools import setup, find_packages


kwargs = {
      'name':'my_package',
      'version':'0.1.0',
      'packages':find_packages(),

       #ensure so-files are copied to the installation:
      'package_data' : { 'my_package': ['*.so']},
      'include_package_data' : True,
      'zip_safe' : False  
}


setup(**kwargs)

现在,在调用python setup.py install之后,该软件包已安装并可以使用:

>>> python -c "import my_package; my_package.foo()"
I'm foo from impl

注意:不要从带有安装文件的文件夹中调用测试,因为这样不能使用已安装的my_package本地版本。


您可能想为不同的Python版本使用不同的二进制文件。可以为不同的Python版本编译相同的扩展名-您必须在生成的共享库中添加正确的后缀,例如:

    在Linux机器上
  • impl.cpython-36m-x86_64-linux-gnu.so用于Python3.6
  • 适用于Python3.7的impl.cpython-37m-x86_64-linux-gnu.so
  • Windows上的
  • impl.cp36-win_amd64.pyd

可以使用

获得当前计算机上扩展名的后缀
>>> import importlib
>>> importlib.machinery.EXTENSION_SUFFIXES
['.cp36-win_amd64.pyd', '.pyd']