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

Mar*_*ery 5 python ctypes

我最近了解到,Python不仅有一个名为的模块ctypes,该模块具有一个docs页面,还有一个名为的模块_ctypes,该模块没有(但在docs中已多次提及)。互联网上的某些代码(例如此Stack Overflow答案中的代码段)使用了这个神秘的未记录_ctypes模块。

进行一些实验表明,这两个模块具有相似但不相同的文档字符串以及重叠但不相同的属性列表:

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']
Run Code Online (Sandbox Code Playgroud)

我暂时认为,也许我看到的是一个“加速器模块”,但我认为不可能,因为当前的ctypes 无条件导入是从中实现的_ctypes。也不清楚这_ctypes仅仅是一个实现细节。它公开了至少一个公共成员,PyObj_FromPtr这是有用的,不能通过ctypes模块使用,并且在CPython源代码中的任何地方都未使用过-也许这表明它是供我们在编写Python代码时导入和使用的?

Python为什么这两个模块的名称基本相同?两者之间的职责划分是什么,我何时要在另一种之上使用?我应该将其_ctypes视为标准库的一部分,还是不应接触的实现细节?

use*_*ica 6

_ctypes之所以会存在,是因为ctypes必须用C编写大量的代码;ctypes_ctypes 这两者之所以存在,是因为并非必须全部ctypes使用C编写代码。它们ctypes包含的部分更易于用Python编写。

_ctypes里面没有开头的下划线,没有暴露的事实ctypes,并不意味着这些东西将被任何东西使用。有时程序只是像那样留有东西。可能有意在开发的某个时刻将其公开。

_ctypes是实施细节。使用ctypes