繁体   English   中英

仅在 setup.py 中可能时才编译可选的 cython 扩展

[英]Compiling an optional cython extension only when possible in setup.py

我有一个在 python 中完全实现的 python 模块。 (出于便携性原因。)

一小部分的实现已复制到一个 cython 模块中。 在可能的情况下提高绩效。

我知道如何使用distutils安装由 cython 创建的.c模块。 但是,如果机器没有安装编译器,我怀疑即使模块在纯 python 模式下仍然可用,安装也会失败。

如果可能,有没有办法编译.c模块,但如果无法编译,则优雅地失败并在没有它的情况下安装?

我想您必须在setup.py和模块中的一个__init__文件中进行一些修改。

假设您的包的名称将是“模块”,并且您有一个功能sub ,您在sub文件夹中有纯 python 代码,在c_sub子文件夹中有等效的 C 代码。 例如在您的setup.py

import logging
from setuptools.extension import Extension
from setuptools.command.build_ext import build_ext
from distutils.errors import CCompilerError, DistutilsExecError, DistutilsPlatformError

logging.basicConfig()
log = logging.getLogger(__file__)

ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError, IOError, SystemExit)

setup_args = {'name': 'module', 'license': 'BSD', 'author': 'xxx',
    'packages': ['module', 'module.sub', 'module.c_sub'],
    'cmdclass': {'build_ext': build_ext}
    }

ext_modules = [Extension("module.c_sub._sub", ["module/c_sub/_sub.c"])]

try:
    # try building with c code :
    setup(ext_modules=ext_modules, **setup_args)
except ext_errors as ex:
    log.warn(ex)
    log.warn("The C extension could not be compiled")

    ## Retry to install the module without C extensions :
    # Remove any previously defined build_ext command class.
    if 'build_ext' in setup_args['cmdclass']:
        del setup_args['cmdclass']['build_ext']

    # If this new 'setup' call don't fail, the module 
    # will be successfully installed, without the C extension :
    setup(**setup_args)
    log.info("Plain-Python installation succeeded.")

现在你需要在你的__init__.py文件中(或在任何与你的情况相关的地方)包含这样的内容:

try:
    from .c_sub import *
except ImportError:
    from .sub import *

通过这种方式,如果构建,将使用 C 版本,否则使用纯 python 版本。 它假定subc_sub将提供相同的 API。

您可以在Shapely包中找到以这种方式执行此操作的安装文件示例 实际上,我发布的大部分代码都是从这个文件中复制( construct_build_ext函数)或改编的(行后)。

Extension在构造函数中具有optional参数:

可选- 指定扩展中的构建失败不应中止构建过程,而只是跳过扩展。

这里还有一个链接指向 mgc提出的一段非常有趣的代码历史。

问题我应该如何构建包含 Cython 代码的 Python 包

是相关的,问题是如何从 Cython 回退到“已经生成的 C 代码”。 您可以使用类似的策略来选择要安装的.py.pyx代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM