超过600个到c python c api的快速python绑定。
pycapi的Python项目详细描述
pycapi是一个python包,包含600多个到c python c api的快速绑定。它的目标是尽可能多地支持Python3.5-3.8稳定的公共API。
要安装,只需运行:
$ pip install pycapi
文件在哪里?
完整的cpython c api文档可以在here中找到。本项目的目标不是维护单独的api引用。
任何类型转换(比如pythonint
with clong
,或者pythonbytes
with cchar*
)都应该是显而易见的,并且所有其他语义(比如refcounts等)都与记录的api行为相同。为了简单起见,pycapi除了cpython有文档记录的稳定的公共api之外,不提供任何其他功能或实用程序。
pycapi怎么比ctypes.pythonapi
更好呢?
更容易使用。
pycapi
按预期工作,开箱即用:
>>>importpycapi>>>pycapi.PyNumber_Add(1,2)3
ctypes.pythonapi
隐式要求用户将参数和返回类型指定为ctypes
类型:
>>>importctypes>>>ctypes.pythonapi.PyNumber_Add(1,2)Segmentationfault:11
>>>importctypes>>>ctypes.pythonapi.PyNumber_Add.argtypes=(ctypes.py_object,ctypes.py_object)>>>ctypes.pythonapi.PyNumber_Add.restype=ctypes.py_object>>>ctypes.pythonapi.PyNumber_Add(1,2)3
更完整。
pycapi
设计用于为any部分c api提供正确类型的绑定,该部分可以从python层调用:
>>>importpycapi>>>pycapi.PyDict_Check({})1
相比之下,ctypes.pythonapi
直接从Python.h
dll加载。因此,它无法提供碰巧作为宏实现的任何api:
>>>importctypes>>>ctypes.pythonapi.PyDict_Check(ctypes.py_object({}))Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>File"/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ctypes/__init__.py",line369,in__getattr__func=self.__getitem__(name)File"/usr/local/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ctypes/__init__.py",line374,in__getitem__func=self._FuncPtr((name_or_ordinal,self))AttributeError:dlsym(RTLD_DEFAULT,PyDict_Check):symbolnotfound
pycapi
在导入时也完全加载,因此您可以使用tab completion和其他内省技术来发现api。ctypes.pythonapi
要求您在加载属性之前访问它,并且无法获得它支持的完整列表。
更快。
在许多情况下,它甚至可以比python层中的内置等效快。数字说明一切:
In[1]:frompycapiimportPyDict_New,PyDict_Clear,PyDict_CopyIn[2]:%timeitPyDict_New()44.7ns±1.38nsperloop(mean±std.dev.of7runs,10000000loopseach)In[3]:%timeitPyDict_Clear({})54ns±0.448nsperloop(mean±std.dev.of7runs,10000000loopseach)In[4]:%timeitPyDict_Copy({})68.9ns±0.362nsperloop(mean±std.dev.of7runs,10000000loopseach)
In[1]:PyDict_New=dict...:PyDict_Clear=dict.clear...:PyDict_Copy=dict.copyIn[2]:%timeitPyDict_New()71.7ns±0.569nsperloop(mean±std.dev.of7runs,10000000loopseach)In[3]:%timeitPyDict_Clear({})55.8ns±0.506nsperloop(mean±std.dev.of7runs,10000000loopseach)In[4]:%timeitPyDict_Copy({})73.1ns±1.06nsperloop(mean±std.dev.of7runs,10000000loopseach)
In[1]:importctypes...:...:PyDict_New=ctypes.pythonapi.PyDict_New...:PyDict_New.argtypes=()...:PyDict_New.restype=ctypes.py_object...:...:PyDict_Clear=ctypes.pythonapi.PyDict_Clear...:PyDict_Clear.argtypes=(ctypes.py_object,)...:PyDict_Clear.restype=None...:...:PyDict_Copy=ctypes.pythonapi.PyDict_Copy...:PyDict_Copy.argtypes=(ctypes.py_object,)...:PyDict_Copy.restype=NoneIn[2]:%timeitPyDict_New()113ns±0.424nsperloop(mean±std.dev.of7runs,10000000loopseach)In[3]:%timeitPyDict_Clear({})273ns±3.34nsperloop(mean±std.dev.of7runs,1000000loopseach)In[4]:%timeitPyDict_Copy({})378ns±9.77nsperloop(mean±std.dev.of7runs,1000000loopseach)