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,对用户来说就越好。

未完待续...

相关推荐
legend_jz6 分钟前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
tangliang_cn26 分钟前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟27 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
新知图书38 分钟前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
威威猫的栗子40 分钟前
Python Turtle召唤童年:喜羊羊与灰太狼之懒羊羊绘画
开发语言·python
力透键背40 分钟前
display: none和visibility: hidden的区别
开发语言·前端·javascript
bluefox197941 分钟前
使用 Oracle.DataAccess.Client 驱动 和 OleDB 调用Oracle 函数的区别
开发语言·c#
ö Constancy1 小时前
c++ 笔记
开发语言·c++
墨染风华不染尘1 小时前
python之开发笔记
开发语言·笔记·python
徐霞客3201 小时前
Qt入门1——认识Qt的几个常用头文件和常用函数
开发语言·c++·笔记·qt