Ctypes 的优缺点
我听说在Python和Windows中使用Ctypes可能会导致崩溃或者错误。那我是不是应该尽量避免使用它呢?我记得我听到这个消息是在我尝试控制Windows的一些功能,做自动化的时候。
我听说过swig,但我发现Ctypes出现得更频繁。这其中有什么危险吗?如果有的话,我应该注意些什么呢?
我确实搜索过关于Ctypes的优缺点。
4 个回答
ctypes
确实可能会导致程序崩溃,尤其是当你使用的 C 库本身就有可能崩溃的时候。
不过,实际上 ctypes
还可以帮助减少崩溃的情况,因为你可以通过 设置 C 函数的 argtypes
属性 来确保运行时的类型安全。
如果你的 C 库已经很稳定并经过测试,那么完全没有理由不使用 ctypes
,只要它能满足你将 C 和 Python 结合起来的需求。
ctypes是一个安全的模块,只要你用得当。
有些库提供了更底层的访问方式,而有些模块则可能让你自己陷入麻烦。所以,自然有些模块比其他的更危险。不过,这并不意味着你就不应该使用它们!
你可能听过有人提到这样的事情:
#Crash python interpreter
from ctypes import *
def crashme():
c = c_char('x')
p = pointer(c)
i = 0
while True:
p[i] = 'x'
i += 1
Python解释器崩溃和Python代码本身出现运行时错误是两回事。例如,如果你写了无限递归,虽然会导致运行时错误,但Python解释器仍然会继续运行。
另一个很好的例子是sys模块。尽管它可能会导致Python解释器崩溃,但你不会因此停止使用sys模块。
import sys
sys.setrecursionlimit(2**30)
def f(x):
f(x+1)
#This will cause no more resources left and then crash the python interpreter
f(1)
还有很多库提供了底层访问。例如,gc模块可以被操控来访问部分构造的对象,访问这些对象的字段可能会导致崩溃。
参考和想法来自:Crashing Python
在稳定性方面,我觉得swig比ctypes要好一些,因为它可以让C编译器帮你更仔细地检查一些东西。不过,现在这个差别已经不那么明显了(在早期的ctypes版本中,这个问题更突出),这要归功于@Mark提到的argtypes
功能。不过,ctypes在运行时的开销确实比swig大得多(还有sip、boost python和其他“包装”方法)。所以,我把ctypes看作是一种方便的方式,可以在不影响性能的情况下,调用DLL中的一些函数,而不是在对性能要求很高的情况下使用它来访问大型C库。
如果你想在swig(和C)的运行时性能和ctypes的便利性之间找到一个不错的折中方案,还可以考虑一下Cython。Cython是一种类似Python的语言,可以编译成C代码,专门用于编写可以被Python调用的扩展和包装C库(包括那些可能只以静态库形式存在的库,ctypes就无法处理这些;-)。