构建 Cython 代码

与 Python 不同,Cython 代码必须编译。这分为两个阶段

  • 一个 .pyx.py 文件由 Cython 编译成一个 .c 文件,其中包含 Python 扩展模块的代码。

  • .c 文件由 C 编译器编译成一个 .so 文件(或 Windows 上的 .pyd),可以直接 import 到 Python 会话中。 setuptools 会处理这部分。虽然 Cython 在某些情况下可以为您调用它们。

要完全理解 Cython + setuptools 构建过程,您可能需要阅读更多关于 分发 Python 模块 的内容。

有几种方法可以构建 Cython 代码

  • 编写 setuptools setup.py。这是正常且推荐的方式。

  • 运行 cythonize 命令行实用程序。这对于将单个 Cython 源文件直接编译成扩展是一个很好的方法。可以使用 cythonize -i filename.pyx 将源文件“就地”构建(以便扩展模块在源文件旁边创建,准备导入)。

  • 使用 Pyximport,将 Cython .pyx 文件导入,就好像它们是 .py 文件一样(使用 setuptools 在后台编译和构建)。这种方法比编写 setup.py 更容易,但不太灵活。因此,如果您需要某些编译选项,则需要编写 setup.py

  • 手动运行 cython 命令行实用程序以从 .pyx 文件生成 .c 文件,然后手动将 .c 文件编译成适合从 Python 导入的共享对象库或 DLL。(这些手动步骤主要用于调试和实验。)

  • 使用 [Jupyter] 笔记本或 [Sage] 笔记本,两者都允许在其中使用 Cython 代码。这是开始编写 Cython 代码并运行它的最简单方法。

目前,使用 setuptools 是构建和分发 Cython 文件最常见的方式。其他方法在参考手册的 源文件和编译 部分中有更详细的描述。

使用 setuptools 构建 Cython 模块

想象一个简单的“hello world”脚本,它位于一个名为 hello.pyx 的文件中

def say_hello_to(name):
    print(f"Hello {name}!")

以下可能是一个相应的 setup.py 脚本

from setuptools import setup
from Cython.Build import cythonize

setup(
    name='Hello world app',
    ext_modules=cythonize("hello.pyx"),
)

要构建,请运行 python setup.py build_ext --inplace。然后,只需启动一个 Python 会话并执行 from hello import say_hello_to,然后根据需要使用导入的函数。

使用 Jupyter 笔记本

Cython 可以通过 Jupyter 笔记本从 Web 浏览器中方便且交互地使用。要安装 Jupyter 笔记本,例如安装到虚拟环境中,请使用 pip

(venv)$ pip install jupyter
(venv)$ jupyter notebook

要启用对 Cython 编译的支持,请按照 安装指南 中的说明安装 Cython,并在 Jupyter 笔记本中加载 Cython 扩展。

%load_ext Cython

然后,在单元格前面加上 %%cython 标记以编译它。

%%cython

a: cython.int = 0
for i in range(10):
    a += i
print(a)

您可以通过传递 --annotate 选项来显示 Cython 的代码分析。

%%cython --annotate
...
../../_images/jupyter.png

有关 %%cython 魔术参数的更多信息,请参见 使用 Jupyter 笔记本进行编译

使用 Sage 笔记本

../../_images/sage.png

对于 Sage 数学发行版的用户,Sage 笔记本允许通过在单元格顶部键入 %cython 并对其进行评估来透明地编辑和编译 Cython 代码。在 Cython 单元格中定义的变量和函数将导入到正在运行的会话中。