天天看点

ctypes python_指南:使用ctypes优化Python代码

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

注:本文中的代码是在GNU AGPLv3下授权的。

当我没有找到一个整体式的使用ctypes的指南时,我写了这个指南。希望这能让别人的生活更轻松一些。

基本优化

在用C语言重写Python源代码之前,请考虑一下这些标准的Python优化。

内置数据结构

Python中内置的数据结构(如set和dict)是用C编写的。它们比将你自己的数据结构编写为Python类要快得多。除了标准的set、dict、list和tuple之外,其他数据结构都记录在collections模块中。

列表推导式

与其向一个列表附加内容,不如使用列表推导式。

ctypes python_指南:使用ctypes优化Python代码

ctypes

ctypes是一个模块,它允许你通过Python代码与C代码进行通信,而不需要使用子进程或类似的模块来从CLI运行另一个进程。

这有两个部分:编译要作为共享对象加载的C代码,并在Python代码中设置数据结构,从而映射到C-types。

在这篇文章中,我将把我的Python代码连接到lcs.c,它可以找到两个字符串列表的最长公共子序列。在Python代码中,我想实现这样的效果:

ctypes python_指南:使用ctypes优化Python代码

这个特殊的C函数的一些挑战是函数签名的参数类型是字符串列表,而返回类型的长度不是固定的。我用一个包含指针和长度的Sequence结构来解决这个问题。

为Python编译C代码

首先,C源代码(lcs.c)被编译为可以被Python装载的lcs.so。

ctypes python_指南:使用ctypes优化Python代码

-Wall显示所有警告。

-Werrow将所有警告变为错误。

-fpic生成“位置无关的指令”,如果你想通过Python使用这个库,这是必须的。

-O3最大化优化。

接下来,我们开始编写Python代码来使用这个共享对象文件。

Python中的结构体

下面,我将展示我的C源代码中使用的两个结构体。

ctypes python_指南:使用ctypes优化Python代码

在这里,你可以看到结构体的Python翻译。

ctypes python_指南:使用ctypes优化Python代码

一些注解:

所有结构体都是从ctypes.Structure继承的class。

惟一的字段是_fields_,它是一个元组列表。每个元组是(, )。

ctypes还有像c_char (char)和c_char_p (*char)这样的类型。

ctypes还包括POINTER(),它会从传递给它的任何类型创建一个指针类型。

如果你有一个类似于CELL中的递归定义,则你必须传递初始声明,然后添加_fields_字段以供以后引用。

由于我在我的Python代码中没有使用CELL,所以我不需要将这个结构体写出来,但是它在递归字段中有一个有趣的特性。

调用你的C代码

另外,你需要一些代码来将Python类型转换为新的C结构。最后,你可以使用新的C函数来加速Python代码。

ctypes python_指南:使用ctypes优化Python代码

更多注解:

**char(字符串列表)在Python中直接映射到字节列表。

lcs.c有一个函数lcs(),它的签名是:struct Sequence *lcs(struct Sequence *s1, struct Sequence *s2)。要设置其返回类型,我使用lcsmodule.lcs.restype = ctypes.POINTER(SEQUENCE)。

为了调用一个对struct Sequence的引用,我使用ctypes.byref(),它返回一个指向你的对象的“轻量级指针”(比ctypes.POINTER()更快)。

common.items是一个字节列表,因此它们被解码后得到的ret将是一个str列表。

lcsmodule.freeSequence(common)只是释放与common相关的内存。这很重要,因为它不会被垃圾回收器(AFAIK)收集。

优化的Python代码: 你用C编写的代码,并用Python为它编写包装器。

额外扩展: PyPy

注:我个人从未使用过PyPy。

一个简单的优化就是在PyPy运行时中运行你的程序,其中包括一个即时(JIT)编译器,当代码循环多次运行时,它会通过将它们编译成本机代码来加速循环。

如果你有任何意见或想进一步讨论,请发邮件给我。

Sam Stevens, 2019年英文原文:https://samuelstevens.me/writing/optimizing-python-code-with-ctypes

译者:野生大熊猫