C桑(Cython)从入坑到入土(1)

Cython 概览 ¶

Cython 是一个将类似 Python 的代码文件编译为 C 代码的编译器。尽管如此,"Cython 不是 Python 到 C 的翻译器"。也就是说,它不会将完整的程序"转换为 C"------相反,结果会充分利用 Python 运行时环境。一种看待它的方式可能是,您的代码仍然是 Python,因为它在 Python 运行时环境中运行,但不是编译为解释型 Python 字节码,而是编译为本机机器代码(但添加了额外的语法,以便轻松嵌入更快的类 C 代码)。

这有两个重要的后果:

  • 速度。不过,多少很大程度上取决于所涉及的计划。典型的 Python 数值程序往往获得的收益很少,因为大部分时间都花在以高级方式使用的较低级别 C 上。然而,当添加键入信息时,for 循环式程序可以获得许多数量级(并且因此成为现实的替代方案)。

  • 轻松调用 C 代码。 Cython 的目的之一是允许轻松包装 C 库。在 Cython 中编写代码时,您可以像调用 Python 代码一样轻松地调用 C 代码。

目前尚不支持极少数 Python 结构,尽管我们的既定目标是让 Cython 编译所有 Python 代码,但您可以看到与 Python 的局限性差异。

您的 Cython 环境 ¶

使用 Cython 包括以下步骤:

  1. 编写 .pyx 源文件

  2. 运行Cython编译器生成C文件

  3. 运行C编译器生成编译库

  4. 运行Python解释器并要求它导入模块

但是,有多种选项可以自动执行这些步骤:

  1. SAGE 数学软件系统为从交互式命令行或通过笔记本界面(如 Maple/Mathematica)使用 Cython 和 NumPy 提供了出色的支持。请参阅此文档。

  2. Cython 可以用作 Jupyter Notebook 中的扩展,只需在单元格顶部添加 %%cython 即可轻松编译和使用 Cython 代码。有关更多信息,请参阅使用 Jupyter Notebook。

  3. Cython 附带了 pyximport 的一个版本,以便您可以将 pyx 文件动态导入到 Python 中并自动编译它们(请参阅使用 pyximport 进行编译)。

  4. Cython 支持 setuptools,因此您可以非常轻松地创建自动执行该过程的构建脚本,这是 Cython 实现的库和包的首选方法。请参阅基本 setup.py

  5. 手动编译(见下文)

注意 如果使用 SAGE 之外的其他交互式命令行环境(例如 IPython 或 Python 本身),则在重新编译模块时重新启动该进程非常重要。仅仅再次发出"进口"声明是不够的。

安装 ¶

如果您已经有 C 编译器,只需执行以下操作:

复制代码
pip install Cython

否则,请参阅安装页面。

截至撰写本文时,SAGE 附带的 Cython 版本比本教程所需的版本更旧。因此,如果使用 SAGE,您应该下载最新的 Cython,然后执行:

复制代码
$ cd path/to/cython-distro
$ path-to-sage/sage -python setup.py install

这会将最新的 Cython 安装到 SAGE 中。

编译 ¶

手动编译 ¶

由于了解正在发生的情况始终很重要,因此我将在这里描述手动方法。第一个 Cython 运行:

复制代码
$ cython yourmod.pyx

这将创建 yourmod.c ,它是 Python 扩展模块的 C 源代码。一个有用的附加开关是 -a ,它将生成一个文档 yourmod.html ),该文档显示哪个 Cython 代码逐行转换为哪个 C 代码。

然后我们编译C文件。这可能会根据您的系统而有所不同,但 C 文件应该像构建 Python 一样构建。用于编写扩展的 Python 文档应该有一些详细信息。在 Linux 上,这通常意味着:

复制代码
$ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.7 -o yourmod.so yourmod.c

gcc 应该有权访问 NumPy C 头文件,因此如果它们未安装在 /usr/include/numpy 或类似位置,您可能需要为这些文件传递另一个选项。如果您编写以下内容,则只需提供 NumPy 标头:

复制代码
cimport numpy

在你的 Cython 代码中。

这会在同一目录中创建 yourmod.so ,Python 可通过使用普通的 importyourmod 语句导入该目录。

使用 setuptools 进行编译 ¶

setuptools 允许我们创建 setup.py 文件来自动编译 Cython 文件和生成的 C 文件:

复制代码
from setuptools import Extension, setup
from Cython.Build import cythonize
import numpy

extensions = [
    Extension("*", ["*.pyx"],
        include_dirs=[numpy.get_include()]),
]
setup(
    name="My hello app",
    ext_modules=cythonize(extensions),
)

NumPy 标头的路径通过 include_dirs=[numpy.get_include()] 参数传递给 C 编译器。

注意 使用内存视图或使用 importnumpy 导入 NumPy 并不意味着您必须添加 NumPy 包含文件的路径。仅当使用 cimportnumpy 时才需要添加此路径。

尽管如此,您仍然可能会从编译器收到如下警告,因为 Cython 不会禁用旧的已弃用的 Numpy API 的使用:

复制代码
.../include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]

在 Cython 3.0 中,您可以通过在构建中将 C 宏 NPY_NO_DEPRECATED_API 定义为 NPY_1_7_API_VERSION 来消除此警告,例如:

复制代码
# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION

或(见下文):

复制代码
Extension(
    ...,
    define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
)

对于较旧的 Cython 版本,设置此宏将使 C 编译失败,因为 Cython 生成使用此已弃用的 C-API 的代码。然而,即使在最近的 NumPy 版本中,该警告也没有负面影响。您可以忽略它,直到您(或您的库的用户)切换到更新的 NumPy 版本,该版本删除了这个长期弃用的 API,在这种情况下,您还需要使用 Cython 3.0 或更高版本。因此,越早切换到 Cython 3.0,对用户来说就越好。

未完待续...

相关推荐
Code Warrior1 小时前
【每日算法】专题五_位运算
开发语言·c++
沐知全栈开发3 小时前
HTML DOM 访问
开发语言
脑袋大大的4 小时前
JavaScript 性能优化实战:减少 DOM 操作引发的重排与重绘
开发语言·javascript·性能优化
二进制person5 小时前
Java SE--方法的使用
java·开发语言·算法
OneQ6665 小时前
C++讲解---创建日期类
开发语言·c++·算法
码农不惑6 小时前
2025.06.27-14.44 C语言开发:Onvif(二)
c语言·开发语言
Coding小公仔8 小时前
C++ bitset 模板类
开发语言·c++
凌肖战8 小时前
力扣网C语言编程题:在数组中查找目标值位置之二分查找法
c语言·算法·leetcode
小赖同学啊8 小时前
物联网数据安全区块链服务
开发语言·python·区块链
shimly1234568 小时前
bash 脚本比较 100 个程序运行时间,精确到毫秒,脚本
开发语言·chrome·bash