ctypes vs _ctypes - почему последний существует? - PullRequest
5 голосов
/ 20 октября 2019

Недавно я узнал, что в Python есть не только модуль с именем ctypes, который имеет страницу документации , но также и модуль с именем _ctypes, который не (но тем не менее упоминается несколько раз в документах ). Некоторый код в Интернете, такой как фрагмент этого ответа о переполнении стека , использует этот загадочный недокументированный _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']

Я на мгновение подумал, что, возможно, то, что я видел, было "ускорительным модулем" , но я думаю, что это не может быть,потому что текущая реализация ctypes безоговорочно импортирует материал из _ctypes. Также не ясно, что _ctypes - это просто деталь реализации;он предоставляет по крайней мере один открытый член, PyObj_FromPtr, который полезен, недоступен через модуль ctypes и не используется где-либо в исходном коде CPython - возможно, предполагает, что он предназначен для импорта и использования при написании кода Python?

Как получилось, что в Python эти два модуля имеют одно и то же имя? Каково разделение обязанностей между ними, и когда я хотел бы использовать одно над другим? Должен ли я считать _ctypes частью стандартной библиотеки или деталью реализации, к которой я не должен прикасаться?

1 Ответ

5 голосов
/ 20 октября 2019

_ctypes существует, потому что очень большое количество ctypes должно быть записано в C. ctypes и _ctypes оба существуют, потому что не все из ctypes должны быть записаны вC. ctypes содержит части, которые было удобнее писать на Python.

Тот факт, что в _ctypes есть вещи без начального подчеркивания, не показанные ctypes, не означает, чтоВещи предназначены для чего-либо. Иногда программы просто так и остаются. Возможно, в какой-то момент разработки было намерение сделать его общедоступным.

_ctypes - это подробность реализации. Используйте ctypes.

...