在Python中,为什么用C语言实现的模块比纯Python模块更快,我怎么写一个?

Pus*_*ade 9 c python python-c-api

python文档说,cPickle比Pickle更快的原因是,前者是用C实现的.这究竟是什么意思?

我正在使用Python制作高级数学模块,有些计算需要花费大量时间.这是否意味着如果我的程序在C中实现,它可以更快?

我想从其他Python程序导入这个模块,就像我可以导入cPickle一样.

你能解释一下如何在C中实现Python模块吗?

Ant*_*Ant 15

你可以编写快速的C代码,然后在你的python脚本中使用它,这样你的程序运行得更快.[1] http://docs.python.org/extending/index.html#extending-index

一个例子是Numpy,用C语言编写(http://numpy.scipy.org/)

一个典型的用法是实现C中的瓶颈(或者使用C编写的库,当然;)),由于它的速度,并使用python进行剩余的代码

[1]顺便说一下,这就是为什么cPickle比pickle更快的原因

编辑:

看看Pyrex:http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/About.html

'Pyrex是一种专为编写Python扩展模块而设计的语言.它旨在弥合优秀的,高级的,易于使用的Python世界与凌乱的低级C世界之间的差距.

这不是"官方"方式,但可能有用

  • +1您应该将核心计算的纯C实现与使用Numpy进行繁重工作的Python实现进行基准测试.Numpy实施很有可能具有竞争力. (2认同)

DSM*_*DSM 8

如上所述,numpy非常适合矢量计算.(可能会更好,但是评论说它比没有实际工作的任何东西都要好,绝对是真的.)

不是什么都可以很容易地矢量化,虽然如此,如果你有大量的函数调用紧凑的内部循环(比如一个大量递归算法),你仍然有几个选项:可能是最流行的是用Cython,它允许你写模块并在一种带注释的Python中运行,并在需要时获得类似C的速度.

或者你的时间都可以通过库调用来计算特征值或反转矩阵或者评估特殊函数或划分非常大的整数 - 顺便说一句,Sage项目中很多都处理得很好,如果你正在做的更多数学而不是纯粹的运算 - 在这种情况下,在Python中花费的时间可能不重要.这一切都取决于你正在做的数字的细节.


Bak*_*riu 7

当您在python中编写函数时,会创建一个新的函数对象,函数代码将被解析并进行字节编译[并保存在"func_code"属性中],因此当您调用该函数时,解释器会读取其字节码并执行它.

如果你在C中编写相同的函数,在C/Python API之后使它在python中可用,解释器将创建函数对象,但是这个函数不会有字节码.当解释器找到对该函数的调用时,它调用真正的C函数,因此它以"机器"速度而不是"python-machine"速度执行.

您可以验证用C编写的检查函数:

>>> map.func_code
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'builtin_function_or_method' object has no attribute 'func_code'
>>> def mymap():pass
... 
>>> mymap.func_code
<code object mymap at 0xcfb5b0, file "<stdin>", line 1>
Run Code Online (Sandbox Code Playgroud)

要了解如何编写用于python的C代码,请按照官方站点中的指南进行操作.

无论如何,如果你只是在进行N维数组计算,那么numpy应该足够了.


Try*_*yPy 5

除了已经提到的Pyrex / Cython,您还有其他选择:

Shed Skin:将Python(的有限子集)翻译成C ++。可以自动为您生成扩展名。您将创建一个扩展来执行此操作(假设使用Linux):

wget http://shedskin.googlecode.com/files/shedskin-0.7.tgz
tar -xzf shedskin-0.7.tgz
# On your code folder:
PYTHONPATH=/path/to/shedskin-0.7 python shedskin -e yourmodule.py
# The above generates a Makefile and a yourmodule.h/.cpp pair
make
# Now you can "import yourmodule" from Python and check it's from the .so by "print yourmodule.__file__
Run Code Online (Sandbox Code Playgroud)

PyPy:更快的Python,带有JIT编译器。您可以简单地在其上运行代码,而不是CPython。现在仅支持Python 2.5,很快将支持2.7。可以大大提高数学上繁重的代码的速度。要安装并运行它(假设Linux为32位):

wget http://pypy.org/download/pypy-1.4.1-linux.tar.bz2
tar -xjf pypy-1.4.1-linux.tar.bz2
sudo ln -s /path/to/pypy-1.4.1-linux/bin/pypy /usr/local/bin
# Then, instead of "python yourprogram.py" you'll just run "pypy yourprogram.py"
Run Code Online (Sandbox Code Playgroud)

编织:允许您内联编写C并进行编译。

编辑:如果您希望我们为您和基准测试运行这些工具,只需发布​​您的代码;)