
Cython 既是一个优化的静态编译器也是一个 Python 的超集的编程语言的名称。作为编译器它可以使用 Python/C API 执行源到源的编译把本地 Python 代码及其 Cython 方言编译为 Python C 扩展。它允许你结合 Python 和 C 的威力而不需要手动处理 Python/C API。Cython 作为源码编译器对于使用 Cython 创建的扩展你将获得的主要优势是使用它提供的语言超集。总之你可以利用源到源的编译使用纯 Python 代码创建扩展。这是 Cython 最简单的方法因为它几乎不需要对代码进行任何修改就可以显著的提升性能并且开发成本也非常低。Cython 提供了一个简单实用的 cythonize 函数允许你轻松地将编译过程与distutils 或 setuptools 集成。假设我们想把一个纯的 Python 实现的 fibonacci()函数编译成一个 C 扩展。如果它位于 fibonacci 模块中最小的 setup.py 脚本如下所示from setuptools import setupfrom Cython.Build import cythonizesetup(name‘fibonacci’,ext_modulescythonize([‘fibonacci.py’]))Cython 用作 Python 语言的源代码编译工具有另一个好处。源到源编译到扩展可以是源分发安装过程的完全可选部分。如果需要安装软件包的环境没有 Cython 或任何其他构建前提条件则可以将其安装为普通的纯 Python 包。用户不需要关注以这种方式分发的代码有任何功能性的行为差异。分发使用 Cython 构建的扩展的常见方法是打包 Python/Cython 源以及从这些源文件生成中的 C 代码。这样根据当前构建前提条件包可以以 3 种不同的方式安装。● 如果安装环境没有可用的 Cython则扩展 C 代码是从提供的 Python/Cython 源中生成。● 如果 Cython 不可用但有可用的构建前提条件C 编译器Python/C API 头扩展是从分散式的预生成的 C 文件中构建。如果前面的先决条件都不可用并且扩展是从纯 Python 源创建的则模块将像普通 Python 代码一样安装并跳过编译步骤。注意包含生成的 C 文件以及 Cython 源文件这是 Cython 文档中推荐的分发 Cython 扩展的方式。文档中还提到默认情况下应该禁用 Cython 编译因为用户在他的环境中可能没有所需的 Cython 版本这可能会导致意想不到的编译问题。不过随着环境隔离的出现现今这似乎是一个不太令人担忧的问题。此外Cython 是一个有效的 Python 包它在 PyPI 上可用因此你可以很容易地定义特定版本的项目依赖。包含这样一个先决条件无疑是一个有严重影响的决定应该非常仔细地考虑。更安全的解决方案是利用 setuptools 包中 extras_require 特性的强大功能并允许用户决定是否要使用具有特定环境变量的 Cython如下所示import osfrom distutils.core import setupfrom distutils.extension import Extensiontry:只有当 Cython 可用时cython 源到源的编译才可以使用import Cython并且特定的环境变量明确说明使用 Cython 生成 c 源码USE_CYTHON bool(os.environ.get(“USE_CYTHON”))except ImportError:USE_CYTHON Falseext ‘.pyx’ if USE_CYTHON else ‘.c’extensions [Extension(“fibonacci”, [“fibonacci”ext])]if USE_CYTHON:from Cython.Build import cythonizeextensions cythonize(extensions)setup(name‘fibonacci’,ext_modulesextensions,extras_require{通过’[with-cython]这个特性当包被安装时可以设置特定的 Cython 的版本的依赖‘cython’: [‘cython0.23.4’]})在安装包时pip 安装工具支持 extras 选项该选项通过向包名称添加[extra-name]后缀进行安装。对于上述示例从本地源安装时可以使用以下命令启用可选的 Cython 依赖与编译器$ USE_CYTHON1 pip install .[with-cython]