我应该如何构建一个包含Cython代码的Python包

Cra*_*een 120 python packaging cython

我想制作一个包含一些Cython代码的Python包.我已经很好地运行了Cython代码.但是,现在我想知道如何最好地打包它.

对于大多数只想安装软件包的人来说,我想要包含.cCython创建的文件,并安排setup.py编译它以生成模块.然后用户不需要安装Cython来安装软件包.

但对于谁可能要修改包的人,我也想提供用Cython .pyx文件,并以某种方式也允许setup.py使用用Cython编译它们(因此这些用户需要安装用Cython).

我应该如何构建包中的文件以满足这两种情况?

用Cython文档提供了一些指导.但它没有说明如何制作一个单独setup.py处理有/无Cython情况.

Cra*_*een 68

我现在自己做了这个,在一个Python包中simplerandom(BitBucket repo - 编辑:现在github)(我不认为这是一个受欢迎的包,但它是一个学习Cython的好机会).

此方法依赖于以下事实:.pyx使用Cython.Distutils.build_ext(至少使用Cython版本0.14)构建文件似乎始终.c在与源.pyx文件相同的目录中创建文件.

这是一个简化版本setup.py,我希望其中包含以下要点:

from distutils.core import setup
from distutils.extension import Extension

try:
    from Cython.Distutils import build_ext
except ImportError:
    use_cython = False
else:
    use_cython = True

cmdclass = {}
ext_modules = []

if use_cython:
    ext_modules += [
        Extension("mypackage.mycythonmodule", ["cython/mycythonmodule.pyx"]),
    ]
    cmdclass.update({'build_ext': build_ext})
else:
    ext_modules += [
        Extension("mypackage.mycythonmodule", ["cython/mycythonmodule.c"]),
    ]

setup(
    name='mypackage',
    ...
    cmdclass=cmdclass,
    ext_modules=ext_modules,
    ...
)
Run Code Online (Sandbox Code Playgroud)

我还进行了编辑,MANIFEST.in以确保它mycythonmodule.c包含在源代码分发中(使用创建的源代码分发python setup.py sdist):

...
recursive-include cython *
...
Run Code Online (Sandbox Code Playgroud)

我不承诺mycythonmodule.c版本控制'trunk'(或Mercurial的'default').当我发布时,我需要记住先做一个python setup.py build_ext,以确保mycythonmodule.c源代码分发的存在和最新.我还创建了一个发布分支,并将C文件提交到分支中.这样我就有了与该版本一起分发的C文件的历史记录.


kyn*_*nan 20

添加到Craig McQueen的答案:请参阅下文,了解如何覆盖sdist命令让Cython在创建源代码分发之前自动编译源文件.

这样你的运行就没有意外分发过时C资源的风险.如果您对分发过程的控制有限,例如从持续集成等自动创建分布时,它也会有所帮助.

from distutils.command.sdist import sdist as _sdist

...

class sdist(_sdist):
    def run(self):
        # Make sure the compiled Cython files in the distribution are up-to-date
        from Cython.Build import cythonize
        cythonize(['cython/mycythonmodule.pyx'])
        _sdist.run(self)
cmdclass['sdist'] = sdist
Run Code Online (Sandbox Code Playgroud)


Col*_*nic 19

http://docs.cython.org/en/latest/src/userguide/source_files_and_compilation.html#distributing-cython-modules

强烈建议您分发生成的.c文件以及Cython源代码,以便用户可以安装模块而无需使用Cython.

还建议在您分发的版本中默认不启用Cython编译.即使用户安装了Cython,他也可能不想仅仅使用它来安装模块.此外,他所拥有的版本可能与您使用的版本不同,并且可能无法正确编译您的源代码.

这只是意味着您附带的setup.py文件将只是生成的.c文件中的正常distutils文件,对于我们将要使用的基本示例:

from distutils.core import setup
from distutils.extension import Extension

setup(
    ext_modules = [Extension("example", ["example.c"])]
)
Run Code Online (Sandbox Code Playgroud)


Len*_*bro 7

最简单的是包括两个但只是使用c文件?包含.pyx文件很不错,但是无论如何都不需要.c文件.想要重新编译.pyx的人可以安装Pyrex并手动完成.

否则,您需要为distutils设置自定义build_ext命令,以便首先构建C文件.Cython已经包含了一个.http://docs.cython.org/src/userguide/source_files_and_compilation.html

该文档没有做的是说如何使这个条件,但

try:
     from Cython.distutils import build_ext
except ImportError:
     from distutils.command import build_ext
Run Code Online (Sandbox Code Playgroud)

应该处理它.


McK*_*vin 5

包含(Cython)生成的 .c 文件非常奇怪。特别是当我们将其包含在 git 中时。我更喜欢使用setuptools_cython。当 Cython 不可用时,它将构建一个内置 Cython 环境的 Egg,然后使用该 Egg 构建代码。

一个可能的例子:https ://github.com/douban/greenify/blob/master/setup.py


更新(2017-01-05):

既然如此setuptools 18.0,就没有必要使用setuptools_cython. 是一个从头开始构建 Cython 项目的示例,无需setuptools_cython.