setup_requires 使用 Cython?

setup_requires with Cython?

我正在为一个带有一些 Cython 扩展模块的项目创建一个 setup.py 文件。

我已经开始工作了:

from setuptools import setup, Extension
from Cython.Build import cythonize

setup(
    name=...,
    ...,
    ext_modules=cythonize([ ... ]),
)

这安装很好。但是,这假定已安装 Cython。如果没有安装怎么办?我知道这就是 setup_requires 参数的用途:

from setuptools import setup, Extension
from Cython.Build import cythonize

setup(
    name=...,
    ...,
    setup_requires=['Cython'],
    ...,
    ext_modules=cythonize([ ... ]),
)

但是,如果尚未安装 Cython,这当然会失败:

$ python setup.py install
Traceback (most recent call last):
  File "setup.py", line 2, in <module>
    from Cython.Build import cythonize
ImportError: No module named Cython.Build

执行此操作的正确方法是什么?我只需要在 setup_requires 步骤运行后以某种方式导入 Cython,但我需要 Cython 才能指定 ext_modules 值。

您必须将 from Cython.Build import cythonize 包装在 try-except 中,并在 except 中将 cythonize 定义为虚拟函数。这样就可以加载脚本而不会因 ImportError.

而失败

然后稍后在处理 setup_requires 参数时,将安装 Cython 并重新执行安装脚本。由于此时已安装 Cython,您将能够成功导入 cythonize

try:
    from Cython.Build import cythonize
except ImportError:
     def cythonize(*args, **kwargs):
         from Cython.Build import cythonize
         return cythonize(*args, **kwargs)

编辑

如评论中所述,在 setuptools 处理缺失的依赖项后,它不会重新加载 Cython。我以前没想过,但你也可以尝试使用后期绑定方法来删除 cythonize

setuptools18.0 版本开始(2015-06-23 发布)可以在 setup_requires 中指定 Cython 并传递 *.pyx 常规 setuptools.Extension:

的模块源
from setuptools import setup, Extension


setup(
    # ...
    setup_requires=[
        # Setuptools 18.0 properly handles Cython extensions.
        'setuptools>=18.0',
        'cython',
    ],
    ext_modules=[
        Extension(
            'mylib',
            sources=['src/mylib.pyx'],
        ),
    ],
)

似乎有第三种方法可以在执行此处描述的实际 setup.py 之前安装构建依赖项(需要 pip):

https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html#basic-setup-

本质上:

  1. 使用以下内容创建文件 pyproject.toml
[build-system]
requires = ["setuptools", "wheel", "Cython"]
  1. 使用 pip install -e . 进行设置