C API Стабильность¶
На C API Python распространяется политика обратной совместимости PEP 387. Хотя C API будет меняться с каждым минорным выпуском (например, с 3.9 на 3.10), большинство изменений будут совместимы с исходным кодом, обычно только путем добавления новых API. Изменение существующего API или удаление API производится только после периода устаревания или для устранения серьезных проблем.
Двоичный интерфейс приложений (ABI) CPython совместим как вперед, так и назад с разными релизами (если они скомпилированы одинаково; см. Платформенные соображения ниже). Таким образом, код, скомпилированный для Python 3.10.0, будет работать на 3.10.8 и наоборот, но для 3.9.x и 3.10.x его нужно будет компилировать отдельно.
Имена с символом подчеркивания, например _Py_InternalState
, являются частными API, которые могут быть изменены без предупреждения даже в выпусках патчей.
Стабильный двоичный интерфейс приложения¶
В Python 3.2 появился Limited API, подмножество C API Python. Расширения, использующие только Limited API, могут быть скомпилированы один раз и работать с несколькими версиями Python. Содержимым Limited API является listed below.
Для этого Python предоставляет Стабильный ABI: набор символов, которые остаются совместимыми во всех версиях Python 3.x. Стабильный ABI содержит символы, открытые в Limited API, а также другие символы - например, функции, необходимые для поддержки старых версий Limited API.
(Для простоты в этом документе говорится о расширениях, но Limited API и Stable ABI работают одинаково для всех случаев использования API - например, для встраивания Python).
-
Py_LIMITED_API
¶ Определите этот макрос перед включением
Python.h
для выбора использования только Limited API, а также для выбора версии Limited API.Определите
Py_LIMITED_API
в значениеPY_VERSION_HEX
, соответствующее самой низкой версии Python, которую поддерживает ваше расширение. Расширение будет работать без перекомпиляции со всеми выпусками Python 3, начиная с указанного, и может использовать Limited API, представленные до этой версии.Вместо того, чтобы использовать макрос
PY_VERSION_HEX
напрямую, жестко задайте минимальную младшую версию (например,0x030A0000
для Python 3.10) для стабильности при компиляции с будущими версиями Python.Вы также можете определить
Py_LIMITED_API
в3
. Это работает так же, как0x03020000
(Python 3.2, версия, в которой появился Limited API).
В Windows расширения, использующие Stable ABI, должны быть связаны с python3.dll
, а не с библиотекой, специфичной для конкретной версии, такой как python39.dll
.
На некоторых платформах Python будет искать и загружать файлы общих библиотек, названные с помощью тега abi3
(например, mymodule.abi3.so
). Он не проверяет, соответствуют ли такие расширения стабильному ABI. Пользователь (или его средства упаковки) должен убедиться, что, например, расширения, созданные с использованием 3.10+ Limited API, не будут установлены для более низких версий Python.
Все функции в стабильном ABI присутствуют как функции в общей библиотеке Python, а не только как макросы. Это делает их пригодными для использования из языков, не использующих препроцессор C.
Ограниченный объем и производительность API¶
Цель ограниченного API - позволить все то, что возможно с полным C API, но, возможно, со снижением производительности.
Например, если PyList_GetItem()
доступен, то его «небезопасный» макросный вариант PyList_GET_ITEM()
- нет. Макрос может быть быстрее, потому что он может полагаться на специфические для конкретной версии детали реализации объекта list.
Без определения Py_LIMITED_API
некоторые функции C API инкрустируются или заменяются макросами. Определение Py_LIMITED_API
отключает эту инкрустацию, обеспечивая стабильность по мере совершенствования структур данных Python, но, возможно, снижая производительность.
Опустив определение Py_LIMITED_API
, можно скомпилировать расширение Limited API с ABI для конкретной версии. Это может повысить производительность для данной версии Python, но ограничит совместимость. Компиляция с использованием Py_LIMITED_API
позволит получить расширение, которое можно распространять там, где нет возможности использовать версию, например, для предварительных версий предстоящей версии Python.
Ограниченные предостережения по API¶
Обратите внимание, что компиляция с помощью Py_LIMITED_API
не является полной гарантией того, что код соответствует ограниченному API или стабильному ABI. Py_LIMITED_API
охватывает только определения, но API также включает другие вопросы, такие как ожидаемая семантика.
Одна проблема, от которой Py_LIMITED_API
не защищает, - это вызов функции с аргументами, которые недопустимы в более низкой версии Python. Например, рассмотрим функцию, которая начинает принимать NULL
в качестве аргумента. В Python 3.9, NULL
теперь выбирает поведение по умолчанию, но в Python 3.8 аргумент будет использоваться напрямую, вызывая разыменование NULL
и крах. Аналогичный аргумент работает для полей структур.
Другая проблема заключается в том, что некоторые поля struct в настоящее время не скрываются при определении Py_LIMITED_API
, хотя они являются частью Limited API.
По этим причинам мы рекомендуем тестировать расширение со всеми минорными версиями Python, которые оно поддерживает, и предпочтительно собирать с низшей такой версией.
Мы также рекомендуем изучить документацию всех используемых API, чтобы проверить, не является ли оно явной частью Limited API. Даже при определенном Py_LIMITED_API
несколько приватных объявлений раскрываются по техническим причинам (или даже непреднамеренно, как ошибки).
Также обратите внимание, что Limited API не обязательно стабилен: компиляция с Py_LIMITED_API
в Python 3.8 означает, что расширение будет работать в Python 3.12, но оно не обязательно компилируется в Python 3.12. В частности, части Limited API могут быть устаревшими и удаленными, при условии, что стабильный ABI остается стабильным.
Платформенные соображения¶
Стабильность ABI зависит не только от Python, но и от используемого компилятора, библиотек нижнего уровня и опций компилятора. Для целей стабильного ABI эти детали определяют «платформу». Обычно они зависят от типа ОС и архитектуры процессора
Каждый конкретный дистрибьютор Python несет ответственность за то, чтобы все версии Python на конкретной платформе были собраны таким образом, чтобы не нарушать Stable ABI. Это относится к выпускам для Windows и macOS от python.org
и многих сторонних дистрибьюторов.
Содержание ограниченного API¶
В настоящее время Limited API включает следующие элементы:
PyBaseObject_Type
PyBool_Type
PyByteArrayIter_Type
PyBytesIter_Type
PyBytes_DecodeEscape()
PyBytes_Repr()
PyCFunction_Call()
PyCFunction_GetFlags()
PyCFunction_GetFunction()
PyCFunction_GetSelf()
PyCFunction_New()
PyCFunction_NewEx()
PyCFunction_Type
PyCMethod_New()
PyCapsule_Type
PyClassMethodDescr_Type
PyDictItems_Type
PyDictIterItem_Type
PyDictIterKey_Type
PyDictIterValue_Type
PyDictKeys_Type
PyDictProxy_Type
PyDictRevIterItem_Type
PyDictRevIterKey_Type
PyDictRevIterValue_Type
PyDictValues_Type
PyEllipsis_Type
PyEnum_Type
PyErr_Display()
PyErr_ProgramText()
PyEval_CallFunction()
PyEval_CallMethod()
PyEval_CallObjectWithKeywords()
PyExc_ArithmeticError
PyExc_AssertionError
PyExc_AttributeError
PyExc_BaseException
PyExc_BlockingIOError
PyExc_BrokenPipeError
PyExc_BufferError
PyExc_BytesWarning
PyExc_ChildProcessError
PyExc_ConnectionAbortedError
PyExc_ConnectionError
PyExc_ConnectionRefusedError
PyExc_ConnectionResetError
PyExc_DeprecationWarning
PyExc_EOFError
PyExc_EncodingWarning
PyExc_EnvironmentError
PyExc_Exception
PyExc_FileExistsError
PyExc_FileNotFoundError
PyExc_FloatingPointError
PyExc_FutureWarning
PyExc_GeneratorExit
PyExc_IOError
PyExc_ImportError
PyExc_ImportWarning
PyExc_IndentationError
PyExc_IndexError
PyExc_InterruptedError
PyExc_IsADirectoryError
PyExc_KeyError
PyExc_KeyboardInterrupt
PyExc_LookupError
PyExc_MemoryError
PyExc_ModuleNotFoundError
PyExc_NameError
PyExc_NotADirectoryError
PyExc_NotImplementedError
PyExc_OSError
PyExc_OverflowError
PyExc_PendingDeprecationWarning
PyExc_PermissionError
PyExc_ProcessLookupError
PyExc_RecursionError
PyExc_ReferenceError
PyExc_ResourceWarning
PyExc_RuntimeError
PyExc_RuntimeWarning
PyExc_StopAsyncIteration
PyExc_StopIteration
PyExc_SyntaxError
PyExc_SyntaxWarning
PyExc_SystemError
PyExc_SystemExit
PyExc_TabError
PyExc_TimeoutError
PyExc_TypeError
PyExc_UnboundLocalError
PyExc_UnicodeDecodeError
PyExc_UnicodeEncodeError
PyExc_UnicodeError
PyExc_UnicodeTranslateError
PyExc_UnicodeWarning
PyExc_UserWarning
PyExc_ValueError
PyExc_Warning
PyExc_WindowsError
PyExc_ZeroDivisionError
PyExceptionClass_Name()
PyFilter_Type
PyGILState_STATE
PyGetSetDescr_Type
PyListIter_Type
PyListRevIter_Type
PyLongRangeIter_Type
PyLong_GetInfo()
PyMap_Type
PyMemberDescr_Type
PyMemoryView_Type
PyMethodDescr_Type
PyModuleDef_Base
PyModuleDef_Type
PyOS_InterruptOccurred()
PyOS_mystricmp()
PyOS_mystrnicmp()
PyOS_sighandler_t
PyOS_strtol()
PyOS_strtoul()
PyObject_ClearWeakRefs()
PyObject_DelItemString()
PyObject_Format()
PyObject_SelfIter()
PyRangeIter_Type
PyRange_Type
PyReversed_Type
PySequence_In()
PySetIter_Type
PySuper_Type
PySys_HasWarnOptions()
PyThread_GetInfo()
PyThread_acquire_lock()
PyThread_acquire_lock_timed()
PyThread_allocate_lock()
PyThread_exit_thread()
PyThread_free_lock()
PyThread_get_stacksize()
PyThread_get_thread_ident()
PyThread_get_thread_native_id()
PyThread_init_thread()
PyThread_release_lock()
PyThread_set_stacksize()
PyThread_start_new_thread()
PyTraceBack_Here()
PyTraceBack_Print()
PyTraceBack_Type
PyTupleIter_Type
PyUnicodeIter_Type
PyUnicode_Append()
PyUnicode_AppendAndDel()
PyUnicode_AsDecodedObject()
PyUnicode_AsDecodedUnicode()
PyUnicode_AsEncodedObject()
PyUnicode_AsEncodedUnicode()
PyUnicode_BuildEncodingMap()
PyUnicode_DecodeCodePageStateful()
PyUnicode_FromOrdinal()
PyUnicode_GetDefaultEncoding()
PyUnicode_InternImmortal()
PyUnicode_Partition()
PyUnicode_RPartition()
PyUnicode_RSplit()
PyUnicode_Resize()
PyVarObject.ob_base
PyWeakReference
PyWrapperDescr_Type
PyZip_Type
Py_FileSystemDefaultEncodeErrors
Py_FileSystemDefaultEncoding
Py_GetRecursionLimit()
Py_HasFileSystemDefaultEncoding
Py_MakePendingCalls()
Py_SetRecursionLimit()
Py_UTF8Mode
Py_intptr_t
Py_uintptr_t
getter
setter
ssizessizeargfunc
ssizessizeobjargproc
symtable