简体   繁体   English

ctypes vs _ctypes - 为什么后者存在?

[英]ctypes vs _ctypes - why does the latter exist?

I recently learned that Python has not only a module named ctypes , which has a docs page , but also a module named _ctypes , which doesn't (but is nonetheless mentioned a few times in the docs ).我最近了解到 Python 不仅有一个名为ctypes的模块,它有一个文档页面,还有一个名为_ctypes的模块,它没有(但仍然在文档中提到了几次)。 Some code on the internet, like the snippet in this Stack Overflow answer , uses this mysterious undocumented _ctypes module.互联网上的一些代码,比如这个 Stack Overflow 答案中的片段,使用了这个神秘的未记录_ctypes模块。

A little experimentation indicates that the two modules have similar but non-identical docstrings and overlapping but non-identical attribute lists:一些实验表明这两个模块具有相似但不相同的文档字符串和重叠但不相同的属性列表:

Python 3.7.4 (default, Sep  7 2019, 18:27:02) 
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes, _ctypes
>>> print(ctypes.__doc__)
create and manipulate C data types in Python
>>> print(_ctypes.__doc__)
Create and manipulate C compatible data types in Python.
>>> dir(ctypes)
['ARRAY', 'ArgumentError', 'Array', 'BigEndianStructure', 'CDLL', 'CFUNCTYPE', 'DEFAULT_MODE', 'LibraryLoader', 'LittleEndianStructure', 'POINTER', 'PYFUNCTYPE', 'PyDLL', 'RTLD_GLOBAL', 'RTLD_LOCAL', 'SetPointerType', 'Structure', 'Union', '_CFuncPtr', '_FUNCFLAG_CDECL', '_FUNCFLAG_PYTHONAPI', '_FUNCFLAG_USE_ERRNO', '_FUNCFLAG_USE_LASTERROR', '_Pointer', '_SimpleCData', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_c_functype_cache', '_calcsize', '_cast', '_cast_addr', '_check_size', '_ctypes_version', '_dlopen', '_endian', '_memmove_addr', '_memset_addr', '_os', '_pointer_type_cache', '_reset_cache', '_string_at', '_string_at_addr', '_sys', '_wstring_at', '_wstring_at_addr', 'addressof', 'alignment', 'byref', 'c_bool', 'c_buffer', 'c_byte', 'c_char', 'c_char_p', 'c_double', 'c_float', 'c_int', 'c_int16', 'c_int32', 'c_int64', 'c_int8', 'c_long', 'c_longdouble', 'c_longlong', 'c_short', 'c_size_t', 'c_ssize_t', 'c_ubyte', 'c_uint', 'c_uint16', 'c_uint32', 'c_uint64', 'c_uint8', 'c_ulong', 'c_ulonglong', 'c_ushort', 'c_void_p', 'c_voidp', 'c_wchar', 'c_wchar_p', 'cast', 'cdll', 'create_string_buffer', 'create_unicode_buffer', 'get_errno', 'memmove', 'memset', 'pointer', 'py_object', 'pydll', 'pythonapi', 'resize', 'set_errno', 'sizeof', 'string_at', 'wstring_at']
>>> dir(_ctypes)
['ArgumentError', 'Array', 'CFuncPtr', 'FUNCFLAG_CDECL', 'FUNCFLAG_PYTHONAPI', 'FUNCFLAG_USE_ERRNO', 'FUNCFLAG_USE_LASTERROR', 'POINTER', 'PyObj_FromPtr', 'Py_DECREF', 'Py_INCREF', 'RTLD_GLOBAL', 'RTLD_LOCAL', 'Structure', 'Union', '_Pointer', '_SimpleCData', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_cast_addr', '_memmove_addr', '_memset_addr', '_pointer_type_cache', '_string_at_addr', '_unpickle', '_wstring_at_addr', 'addressof', 'alignment', 'buffer_info', 'byref', 'call_cdeclfunction', 'call_function', 'dlclose', 'dlopen', 'dlsym', 'get_errno', 'pointer', 'resize', 'set_errno', 'sizeof']

I momentarily thought that perhaps what I was seeing was an "accelerator module" , but I think it can't be, because the current implementation of ctypes unconditionally imports stuff from _ctypes .我一时想,也许我看到的是一个“加速器模块” ,但我认为不可能,因为当前的ctypes实现无条件地_ctypes导入东西。 Nor is it clear that _ctypes is just an implementation detail; _ctypes只是一个实现细节也不清楚。 it exposes at least one public member, PyObj_FromPtr , that is useful, not available via the ctypes module, and not used anywhere within the CPython source - perhaps suggesting that it's meant for us to import and use when writing Python code?它公开了至少一个公共成员PyObj_FromPtr ,这是有用的,不能通过ctypes模块获得,也不能在 CPython 源代码中的任何地方使用 - 也许暗示它是为了让我们在编写 Python 代码时导入和使用?

How come Python has these two modules with basically the same name?怎么Python这两个模块名字基本一样? What's the division of responsibilities between the two, and when would I want to use one over the other?两者之间的职责分工是什么,我什么时候想使用一个而不是另一个? Should I regard _ctypes as a part of the standard library, or as an implementation detail that I shouldn't be touching?我应该将_ctypes视为标准库的一部分,还是我不应该触及的实现细节?

_ctypes exists because a very large amount of ctypes has to be written in C. _ctypes存在是因为必须在 C 中写入大量ctypes ctypes and _ctypes both exist because not all of ctypes has to be written in C. ctypes_ctypes存在,因为并非所有ctypes都必须写入 C。 ctypes contains the parts that were more convenient to write in Python. ctypes包含 Python 中更方便编写的部分。

The fact that _ctypes has things in it with no leading underscore, not exposed by ctypes , does not mean that those things are meant to be used by anything. _ctypes里面有没有前导下划线的东西,没有被ctypes暴露,这并不意味着这些东西可以被任何东西使用。 Sometimes programs just have stuff left lying around like that.有时程序只是像这样留下一些东西。 There might have been an intent to make it public at some point in development.可能有打算在开发的某个阶段将其公开。

_ctypes is an implementation detail. _ctypes是一个实现细节。 Use ctypes .使用ctypes

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM