intro.md
1> **Источник:** https://python-all.ru/3.16/c-api/intro.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Введение89Интерфейс прикладного программирования Python предоставляет программистам на C и C++ доступ к интерпретатору Python на различных уровнях. API одинаково пригоден для использования из C++, но для краткости его обычно называют Python/C API. Есть две принципиально разные причины для использования Python/C API. Первая – написание *модулей расширения* для конкретных целей; это модули на C, которые расширяют интерпретатор Python. Вероятно, это наиболее распространённое применение. Вторая – использование Python как компонента в более крупном приложении; этот метод обычно называют *встраиванием* Python в приложение.1011Написание модуля расширения – относительно хорошо понятный процесс, где хорошо работает подход «кулинарной книги» (cookbook). Существует несколько инструментов, которые в некоторой степени автоматизируют этот процесс. Хотя Python встраивали в другие приложения с самого начала его существования, процесс встраивания Python менее прямолинейный, чем написание расширения.1213Многие функции API полезны независимо от того, встраивается Python или расширяется; более того, большинство приложений, встраивающих Python, также должны предоставлять собственное расширение, поэтому, вероятно, стоит ознакомиться с написанием расширения, прежде чем пытаться встроить Python в реальное приложение.1415## Совместимость версий языка1617C API Python совместим с версиями C11 и C++11 языков C и C++.1819Это нижняя граница: C API не требует возможностей более поздних версий C/C++. *не* нужно включать режим c11 компилятора.2021## Стандарты кодирования2223При написании кода на C для включения в CPython **необходимо** следовать рекомендациям и стандартам, определённым в [**PEP 7**](https://python-all.ru/3.16/c-api/intro.html). Эти рекомендации действуют независимо от версии Python, в которую вносится вклад. Следование этим соглашениям не обязательно для собственных сторонних модулей расширения, если не планируется в конечном счёте передать их в Python.2425## Заголовочные файлы2627Все определения функций, типов и макросов, необходимые для использования Python/C API, включаются в код с помощью следующей строки:2829```c30#define PY_SSIZE_T_CLEAN31#include <Python.h>32```3334Это подразумевает включение следующих стандартных заголовочных файлов: `<stdio.h>`, `<string.h>`, `<errno.h>`, `<limits.h>`, `<assert.h>` и `<stdlib.h>` (если доступны).3536> **Примечание**37>38> Поскольку Python может определять некоторые определения препроцессора, которые влияют на стандартные заголовочные файлы в некоторых системах, *необходимо* включать `Python.h` перед включением любых стандартных заголовочных файлов.39>40> Рекомендуется всегда определять `PY_SSIZE_T_CLEAN` перед включением `Python.h`. См. [Разбор аргументов и создание значений](https://python-all.ru/3.16/c-api/arg.html#arg-parsing) для описания этого макроса.4142Все видимые пользователю имена, определённые Python.h (кроме тех, что определены включёнными стандартными заголовками), имеют один из префиксов `Py` или `_Py`. Имена, начинающиеся с `_Py`, предназначены для внутреннего использования реализацией Python и не должны использоваться разработчиками расширений. Имена членов структур не имеют зарезервированного префикса.4344> **Примечание**45>46> Пользовательский код никогда не должен определять имена, начинающиеся с `Py` или `_Py`. Это сбивает с толку читателя и ставит под угрозу переносимость пользовательского кода на будущие версии Python, которые могут определять дополнительные имена, начинающиеся с одного из этих префиксов.4748Заголовочные файлы обычно устанавливаются вместе с Python. В Unix они находятся в каталогах `prefix/include/pythonversion/` и `exec_prefix/include/pythonversion/`, где [`prefix`](https://python-all.ru/3.16/using/configure.html#cmdoption-prefix) и [`exec_prefix`](https://python-all.ru/3.16/using/configure.html#cmdoption-exec-prefix) определяются соответствующими параметрами сценария **configure** Python, а *version* – `'%d.%d' % sys.version_info[:2]`. В Windows заголовочные файлы устанавливаются в `prefix/include`, где `prefix` – каталог установки, указанный в программе установки.4950Чтобы включить заголовочные файлы, поместите оба каталога (если они разные) в путь поиска include компилятора. *Не* помещайте родительские каталоги в путь поиска, а затем используйте `#include <pythonX.Y/Python.h>`; это нарушит сборку на нескольких платформах, поскольку независимые от платформы заголовочные файлы в [`prefix`](https://python-all.ru/3.16/using/configure.html#cmdoption-prefix) включают специфичные для платформы заголовочные файлы из [`exec_prefix`](https://python-all.ru/3.16/using/configure.html#cmdoption-exec-prefix).5152Пользователям C++ следует отметить, что, хотя API полностью определён с использованием C, заголовочные файлы правильно объявляют точки входа как `extern "C"`. В результате нет необходимости делать что-то особенное для использования API из C++.5354### Системные включения5556> `Python.h` включает несколько стандартных заголовочных файлов. Расширения C должны включать те стандартные заголовочные файлы, которые они используют, и не должны полагаться на эти неявные включения. Неявные включения:57>58> - `<assert.h>`59> - `<intrin.h>` (в Windows)60> - `<inttypes.h>`61> - `<limits.h>`62> - `<math.h>`63> - `<stdarg.h>`64> - `<string.h>`65> - `<wchar.h>`66> - `<sys/types.h>` (если присутствует)67>68> Следующие включены для обратной совместимости, если только не используется [Limited API](https://python-all.ru/3.16/c-api/stable.html#limited-c-api) 3.13 или новее:69>70> - `<ctype.h>`71> - `<unistd.h>` (в POSIX)72>73> Следующие включены для обратной совместимости, если только не используется [Limited API](https://python-all.ru/3.16/c-api/stable.html#limited-c-api) 3.11 или новее:74>75> - `<errno.h>`76> - `<stdio.h>`77> - `<stdlib.h>`7879> **Примечание**80>81> Поскольку Python может определять некоторые директивы препроцессора, которые влияют на стандартные заголовочные файлы в некоторых системах, *необходимо* включать `Python.h` до того, как будут включены любые стандартные заголовочные файлы.8283## Полезные макросы8485В заголовочных файлах Python определено несколько полезных макросов. Многие из них определены рядом с местом их использования (например, [`Py_RETURN_NONE`](https://python-all.ru/3.16/c-api/none.html#c.Py_RETURN_NONE), [`PyMODINIT_FUNC`](https://python-all.ru/3.16/c-api/extension-modules.html#c.PyMODINIT_FUNC)). Другие, более общего назначения, определены здесь. Этот список не обязательно полон.8687#### `Py_CAN_START_THREADS`8889Если этот макрос определён, то текущая система может запускать потоки.9091В настоящее время все системы, поддерживаемые CPython (согласно [**PEP 11**](https://python-all.ru/3.16/c-api/intro.html)), за исключением некоторых платформ WebAssembly, поддерживают запуск потоков.9293Добавлено в версии 3.13.9495#### `Py_GETENV(s)`9697Как `getenv(s)`, но возвращает `NULL`, если [`-E`](https://python-all.ru/3.16/using/cmdline.html#cmdoption-E) был передан в командной строке (см. [`PyConfig.use_environment`](https://python-all.ru/3.16/c-api/init_config.html#c.PyConfig.use_environment)).9899### Макросы строк документации100101#### `PyDoc_STRVAR(name, str)`102103Создаёт переменную с именем *name*, которую можно использовать в строках документации. Если Python собран без строк документации ([`--without-doc-strings`](https://python-all.ru/3.16/using/configure.html#cmdoption-without-doc-strings)), значением будет пустая строка.104105Пример:106107```c108PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element.");109110static PyMethodDef deque_methods[] = {111 // ...112 {"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc},113 // ...114}115```116117Расширяется до `PyDoc_VAR(name) = PyDoc_STR(str)`.118119#### `PyDoc_STR(str)`120121Расширяется до заданной входной строки или пустой строки, если строки документации отключены ([`--without-doc-strings`](https://python-all.ru/3.16/using/configure.html#cmdoption-without-doc-strings)).122123Пример:124125```c126static PyMethodDef pysqlite_row_methods[] = {127 {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS,128 PyDoc_STR("Returns the keys of the row.")},129 {NULL, NULL}130};131```132133#### `PyDoc_VAR(name)`134135Объявляет статическую переменную-массив символов с заданным именем *name*. Расширяется до `static const char name[]`136137Например:138139```c140PyDoc_VAR(python_doc) = PyDoc_STR(141 "A genus of constricting snakes in the Pythonidae family native "142 "to the tropics and subtropics of the Eastern Hemisphere.");143```144145### Макросы общего назначения146147Следующие макросы предназначены для общих задач, не специфичных для Python.148149#### `Py_UNUSED(arg)`150151Используется для неиспользуемых аргументов в определении функции, чтобы подавить предупреждения компилятора. Пример: `int func(int a, int Py_UNUSED(b)) { return a; }`.152153Добавлено в версии 3.4.154155#### `Py_GCC_ATTRIBUTE(name)`156157Использует атрибут GCC *name*, скрывая его от компиляторов, не поддерживающих атрибуты GCC (например, MSVC).158159Расширяется до `__attribute__((name))` на компиляторе GCC и не расширяется на компиляторах, которые не поддерживают атрибуты GCC.160161#### Числовые утилиты162163#### `Py_ABS(x)`164165Возвращает абсолютное значение `x`.166167Аргумент может вычисляться более одного раза. Следовательно, не передавайте в этот макрос выражение с побочными эффектами напрямую.168169Если результат не может быть представлен (например, если `x` имеет значение `INT_MIN` для типа int), поведение не определено.170171Примерно соответствует `((x) < 0 ? -(x) : (x))`172173Добавлено в версии 3.3.174175#### `Py_MAX(x, y)`176177#### `Py_MIN(x, y)`178179Возвращает больший или меньший из аргументов, соответственно.180181Любые аргументы могут вычисляться более одного раза. Следовательно, не передавайте в этот макрос выражение с побочными эффектами напрямую.182183`Py_MAX` примерно соответствует `(((x) > (y)) ? (x) : (y))`.184185Добавлено в версии 3.3.186187#### `Py_ARITHMETIC_RIGHT_SHIFT(type, integer, positions)`188189Аналогично `integer >> positions`, но принудительно расширяет знак, так как стандарт C не определяет, будет ли сдвиг вправо знакового целого числа расширять знак или заполнять нулями.190191*integer* должен быть любым знаковым целым типом. *positions* – количество позиций для сдвига вправо.192193И *integer*, и *positions* могут вычисляться более одного раза; поэтому избегайте прямой передачи вызова функции или другой операции с побочными эффектами в этот макрос. Вместо этого сохраните результат в переменную и затем передайте его.194195*type* не используется и сохранён только для обратной совместимости. Исторически *type* использовался для приведения *integer*.196197Изменено в версии 3.1: Этот макрос теперь действителен для всех знаковых целых типов, а не только тех, для которых `unsigned type` допустим. В результате *type* больше не используется.198199#### `Py_CHARMASK(c)`200201Аргумент должен быть символом или целым числом в диапазоне \[-128, 127\] или \[0, 255\]. Этот макрос возвращает `c`, приведённый к `unsigned char`.202203#### Утилиты для утверждений204205#### `Py_UNREACHABLE()`206207Используйте этот макрос, когда есть путь выполнения, который по замыслу не может быть достигнут. Например, в ветке `default:` оператора `switch`, для которого все возможные значения покрыты ветками `case`. Используйте его в местах, где вы могли бы попытаться поместить вызов `assert(0)` или `abort()`.208209В релизном режиме макрос помогает компилятору оптимизировать код и избегает предупреждения о недостижимом коде. Например, макрос реализован с помощью `__builtin_unreachable()` в GCC в релизном режиме.210211В режиме отладки и на неподдерживаемых компиляторах макрос раскрывается в вызов [`Py_FatalError()`](https://python-all.ru/3.16/c-api/sys.html#c.Py_FatalError).212213Одно из применений `Py_UNREACHABLE()` – после вызова функции, которая никогда не возвращает управление, но не объявлена как `_Noreturn`.214215Если путь выполнения является крайне маловероятным, но может быть достигнут в исключительных случаях, этот макрос использовать нельзя. Например, при нехватке памяти или если системный вызов возвращает значение за пределами ожидаемого диапазона. В этом случае лучше сообщить об ошибке вызывающему коду. Если ошибка не может быть сообщена вызывающему коду, можно использовать [`Py_FatalError()`](https://python-all.ru/3.16/c-api/sys.html#c.Py_FatalError).216217Добавлено в версии 3.7.218219#### `Py_SAFE_DOWNCAST(value, larger, smaller)`220221Приводит *value* к типу *smaller* из типа *larger*, проверяя, что ни одна информация не была потеряна.222223В релизных сборках Python это примерно эквивалентно `((smaller) value)` (в C++ будет использоваться `static_cast<smaller>(value)`).224225В отладочных сборках (подразумевая, что определён [`Py_DEBUG`](https://python-all.ru/3.16/c-api/intro.html#c.Py_DEBUG)) это утверждает, что при приведении от *larger* к *smaller* не было потеряно информации.226227*value*, *larger* и *smaller* могут вычисляться более одного раза в выражении; следовательно, не передавайте в этот макрос выражение с побочными эффектами напрямую.228229#### `Py_BUILD_ASSERT(cond)`230231Утверждает условие времени компиляции *cond* в виде инструкции. Сборка завершится ошибкой, если условие ложно или не может быть вычислено во время компиляции.232233Примерно соответствует `static_assert(cond)` в C23 и новее.234235Например:236237```c238Py_BUILD_ASSERT(sizeof(PyTime_t) == sizeof(int64_t));239```240241Добавлено в версии 3.3.242243#### `Py_BUILD_ASSERT_EXPR(cond)`244245Asserts a compile-time condition *cond*, as an expression that evaluates to `0`. The build will fail if the condition is false or cannot be evaluated at compile time.246247Например:248249```c250#define foo_to_char(foo) \251 ((char *)(foo) + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0))252```253254Добавлено в версии 3.3.255256#### Утилиты для определения размера типов257258#### `Py_ARRAY_LENGTH(array)`259260Вычисляет длину статически выделенного C-массива во время компиляции.261262Аргумент *array* должен быть C-массивом с размером, известным на этапе компиляции. Передача массива с неизвестным размером, например, выделенного в куче, приведёт к ошибке компиляции в некоторых компиляторах или даст неверные результаты.263264Это примерно эквивалентно:265266```c267sizeof(array) / sizeof((array)[0])268```269270#### `Py_MEMBER_SIZE(type, member)`271272Возвращает размер поля *member* структуры (*type*) в байтах.273274Примерно соответствует `sizeof(((type *)NULL)->member)`.275276Добавлено в версии 3.6.277278#### Утилиты для определения макросов279280#### `Py_FORCE_EXPANSION(X)`281282Это эквивалентно `X`, что полезно для склеивания токенов в макросах, так как раскрытие макросов в *X* принудительно вычисляется препроцессором.283284#### `Py_STRINGIFY(x)`285286Преобразует `x` в C-строку. Например, `Py_STRINGIFY(123)` возвращает `"123"`.287288Добавлено в версии 3.4.289290### Утилиты для объявлений291292Следующие макросы можно использовать в объявлениях. Они наиболее полезны для определения самого C API и имеют ограниченное применение для разработчиков расширений. Большинство из них раскрываются в специфичные для компилятора варианты распространённых расширений языка C.293294#### `Py_ALWAYS_INLINE`295296Предлагает компилятору всегда встраивать статическую встраиваемую функцию. Компилятор может проигнорировать это и решить не встраивать функцию.297298Соответствует атрибуту `always_inline` в GCC и `__forceinline` в MSVC.299300Его можно использовать для встраивания критичных по производительности статических встраиваемых функций при сборке Python в режиме отладки с отключённым встраиванием функций. Например, MSC отключает встраивание функций при сборке в режиме отладки.301302Слепое пометивание статической встраиваемой функции макросом Py\_ALWAYS\_INLINE может привести к ухудшению производительности (например, из-за увеличения размера кода). Компилятор обычно умнее разработчика в анализе затрат и выгод.303304Если Python [собран в режиме отладки](https://python-all.ru/3.16/using/configure.html#debug-build) (если определён макрос [`Py_DEBUG`](https://python-all.ru/3.16/c-api/intro.html#c.Py_DEBUG)), макрос [`Py_ALWAYS_INLINE`](https://python-all.ru/3.16/c-api/intro.html#c.Py_ALWAYS_INLINE) ничего не делает.305306Он должен быть указан перед типом возвращаемого значения функции. Использование:307308```c309static inline Py_ALWAYS_INLINE int random(void) { return 4; }310```311312Добавлено в версии 3.12.313314#### `Py_NO_INLINE`315316Отключает встраивание функции. Например, это уменьшает потребление стека C: полезно при сборках с LTO+PGO, которые активно встраивают код (см. [bpo-33720](https://python-all.ru/3.16/c-api/intro.html)).317318Соответствует атрибуту/спецификации `noinline` в GCC и MSVC.319320Использование:321322```c323Py_NO_INLINE static int random(void) { return 4; }324```325326Добавлено в версии 3.12.327328#### `Py_DEPRECATED(version)`329330Используйте этот макрос для объявления API, которые были помечены как устаревшие в определённой версии CPython. Макрос должен быть размещён перед именем символа.331332Пример:333334```c335Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);336```337338Изменено в версии 3.8: добавлена поддержка MSVC.339340#### `Py_LOCAL(type)`341342Объявляет функцию, возвращающую указанный *тип*, с квалификатором быстрого вызова для функций, локальных для текущего файла. Семантически это эквивалентно `static type`.343344#### `Py_LOCAL_INLINE(type)`345346Эквивалентно [`Py_LOCAL`](https://python-all.ru/3.16/c-api/intro.html#c.Py_LOCAL), но дополнительно требует встраивания функции.347348#### `Py_LOCAL_SYMBOL`349350Макрос, используемый для объявления символа как локального для общей библиотеки (скрытого). На поддерживаемых платформах гарантирует, что символ не экспортируется.351352В совместимых версиях GCC/Clang раскрывается в `__attribute__((visibility("hidden")))`.353354#### `Py_EXPORTED_SYMBOL`355356Макрос, используемый для объявления символа (функции или данных) как экспортируемого. В Windows раскрывается в `__declspec(dllexport)`. В совместимых версиях GCC/Clang раскрывается в `__attribute__((visibility("default")))`. Этот макрос предназначен для определения самого C API; модули расширения не должны его использовать.357358#### `Py_IMPORTED_SYMBOL`359360Макрос, используемый для объявления символа как импортируемого. В Windows раскрывается в `__declspec(dllimport)`. Этот макрос предназначен для определения самого C API; модули расширения не должны его использовать.361362#### `PyAPI_FUNC(type)`363364Макрос, используемый CPython для объявления функции как части C API. Его раскрытие зависит от платформы и конфигурации сборки. Этот макрос предназначен для определения самого C API CPython; модули расширения не должны использовать его для своих собственных символов.365366#### `PyAPI_DATA(type)`367368Макрос, используемый CPython для объявления публичной глобальной переменной как части C API. Его раскрытие зависит от платформы и конфигурации сборки. Этот макрос предназначен для определения самого C API CPython; модули расширения не должны использовать его для своих собственных символов.369370### Устаревшие макросы371372Следующие [мягко устаревшие](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) макросы использовались для функций, которые были стандартизированы в C11 (или более ранних стандартах).373374#### `Py_ALIGNED(num)`375376В некоторых компиляторах, подобных GCC, задаёт выравнивание до *num* байт. В других компиляторах ничего не делает.377378Используйте стандартный спецификатор `alignas` вместо этого макроса.379380[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.381382#### `PY_FORMAT_SIZE_T`383384Модификатор форматирования `printf()` для `size_t`. Используйте напрямую `"z"`.385386[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.387388#### `Py_LL(number)`389390#### `Py_ULL(number)`391392Используйте *number* как целочисленный литерал `long long` или `unsigned long long`, соответственно.393394Раскрывается в *number*, за которым следует `LL` или `LLU` соответственно, но в некоторых старых компиляторах будет раскрываться в некоторые специфичные для компилятора суффиксы.395396Рекомендуется использовать стандартные суффиксы C99 `LL` и `LLU` напрямую.397398[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.399400#### `PY_LONG_LONG`401402#### `PY_INT32_T`403404#### `PY_UINT32_T`405406#### `PY_INT64_T`407408#### `PY_UINT64_T`409410Псевдонимы для типов `long long`, `int32_t`, `uint32_t`. `int64_t` и `uint64_t` соответственно. Исторически эти типы требовали специфичных для компилятора расширений.411412[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.413414#### `PY_LLONG_MIN`415416#### `PY_LLONG_MAX`417418#### `PY_ULLONG_MAX`419420#### `PY_SIZE_MAX`421422Псевдонимы для значений `LLONG_MIN`, `LLONG_MAX`, `ULLONG_MAX` и `SIZE_MAX` соответственно. Вместо этого используйте эти стандартные имена.423424Требуемый заголовочный файл, `<limits.h>`, [включается](https://python-all.ru/3.16/c-api/intro.html#capi-system-includes) в `Python.h`.425426[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.427428#### `Py_MEMCPY(dest, src, n)`429430Это псевдоним `memcpy()`.431432[Мягко устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.14: Вместо этого используйте непосредственно `memcpy()`.433434#### `Py_UNICODE_SIZE`435436Размер типа `wchar_t`. Используйте `sizeof(wchar_t)` или `WCHAR_WIDTH/8`.437438Требуемый заголовочный файл для последнего, `<limits.h>`, [включается](https://python-all.ru/3.16/c-api/intro.html#capi-system-includes) в `Python.h`.439440[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.441442#### `Py_UNICODE_WIDE`443444Определено, если `wchar_t` может содержать символ Unicode (UCS-4). Вместо этого используйте `sizeof(wchar_t) >= 4`.445446[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.447448#### `Py_VA_COPY`449450Это псевдоним функции `va_copy` стандарта C99.451452Исторически для копирования `va_list` использовался метод, зависящий от конкретного компилятора.453454Изменено в версии 3.6: Теперь это псевдоним для `va_copy`.455456[Условно устарело](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) с версии 3.15.457458## Объекты, типы и счетчики ссылок459460Большинство функций Python/C API имеют один или несколько аргументов, а также возвращаемое значение типа [PyObject](https://python-all.ru/3.16/c-api/structures.html#c.PyObject)\*. Этот тип является указателем на непрозрачный тип данных, представляющий произвольный объект Python. Поскольку все типы объектов Python обрабатываются одинаково в большинстве ситуаций (например, присваивание, правила области видимости и передача аргументов), вполне уместно, чтобы они представлялись одним типом C. Почти все объекты Python живут в куче: никогда не объявляются автоматические или статические переменные типа [`PyObject`](https://python-all.ru/3.16/c-api/structures.html#c.PyObject), можно объявлять только переменные-указатели типа PyObject\*. Единственным исключением являются объекты типа; поскольку они никогда не должны освобождаться, они обычно являются статическими объектами [`PyTypeObject`](https://python-all.ru/3.16/c-api/type.html#c.PyTypeObject).461462Все объекты Python (даже целые числа Python) имеют *тип* и *счетчик ссылок*. Тип объекта определяет, что это за объект (например, целое число, список или пользовательская функция; существует гораздо больше типов, как описано в [Стандартная иерархия типов](https://python-all.ru/3.16/reference/datamodel.html#types)). Для каждого из известных типов существует макрос, проверяющий, является ли объект объектом этого типа; например, `PyList_Check(a)` истинно тогда и только тогда, когда объект, на который указывает *a*, является списком Python.463464### Счетчики ссылок465466Счетчик ссылок важен, потому что современные компьютеры имеют конечный (и часто сильно ограниченный) размер памяти; он подсчитывает, сколько различных мест имеют [сильную ссылку](https://python-all.ru/3.16/glossary.html#term-strong-reference) на объект. Таким местом может быть другой объект, глобальная (или статическая) переменная C или локальная переменная в какой-либо функции C. Когда последняя сильная ссылка на объект освобождается (т.е. его счетчик ссылок становится нулевым), объект освобождается. Если он содержит ссылки на другие объекты, эти ссылки освобождаются. Эти другие объекты могут быть освобождены в свою очередь, если на них больше нет ссылок, и так далее. (Здесь очевидна проблема с объектами, ссылающимися друг на друга; на данный момент решение – «не делайте так».)467468Счетчики ссылок всегда изменяются явным образом. Обычный способ – использовать макрос [`Py_INCREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_INCREF) для получения новой ссылки на объект (т.е. увеличить его счетчик ссылок на единицу) и [`Py_DECREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_DECREF) для освобождения этой ссылки (т.е. уменьшить счетчик ссылок на единицу). Макрос `Py_DECREF()` значительно сложнее, чем макрос incref, поскольку он должен проверять, не стал ли счетчик ссылок нулевым, и затем вызывать деаллокатор объекта. Деаллокатор – это указатель на функцию, содержащийся в структуре типа объекта. Деаллокатор, специфичный для типа, отвечает за освобождение ссылок на другие объекты, содержащиеся в объекте, если это составной тип объекта (например, список), а также за выполнение любой дополнительной финализации, которая требуется. Нет возможности переполнения счетчика ссылок; для хранения счетчика ссылок используется по крайней мере столько битов, сколько существует различных ячеек памяти в виртуальной памяти (при условии `sizeof(Py_ssize_t) >= sizeof(void*)`). Таким образом, увеличение счетчика ссылок – простая операция.469470Нет необходимости удерживать [сильную ссылку](https://python-all.ru/3.16/glossary.html#term-strong-reference) (т.е. увеличивать счетчик ссылок) для каждой локальной переменной, содержащей указатель на объект. Теоретически счетчик ссылок объекта увеличивается на единицу, когда переменная начинает указывать на него, и уменьшается на единицу, когда переменная выходит из области видимости. Однако эти два действия компенсируют друг друга, поэтому в итоге счетчик ссылок не меняется. Единственная реальная причина использовать счетчик ссылок – предотвратить освобождение объекта, пока наша переменная указывает на него. Если мы знаем, что существует по крайней мере одна другая ссылка на объект, которая живет как минимум столько же, сколько наша переменная, нет необходимости временно получать новую сильную ссылку (т.е. увеличивать счетчик ссылок). Важная ситуация, в которой это возникает, – объекты, передаваемые в качестве аргументов функциям C в модуле расширения, которые вызываются из Python; механизм вызова гарантирует удержание ссылки на каждый аргумент на время вызова.471472Однако распространенная ошибка – извлечь объект из списка и удерживать его некоторое время, не получая новую ссылку. Какая-нибудь другая операция может удалить объект из списка, освободив эту ссылку, и, возможно, освободить его. Реальная опасность в том, что безобидные на первый взгляд операции могут вызвать произвольный код Python, который способен это сделать; существует путь выполнения, который позволяет управлению вернуться к пользователю из [`Py_DECREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_DECREF), поэтому практически любая операция потенциально опасна.473474Безопасный подход – всегда использовать обобщенные операции (функции, имя которых начинается с `PyObject_`, `PyNumber_`, `PySequence_` или `PyMapping_`). Эти операции всегда создают новую [сильную ссылку](https://python-all.ru/3.16/glossary.html#term-strong-reference) (т.е. увеличивают счетчик ссылок) возвращаемого объекта. Это возлагает на вызывающего обязанность вызвать [`Py_DECREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_DECREF), когда он закончит работу с результатом; это быстро входит в привычку.475476#### Подробности о счетчиках ссылок477478Поведение функций Python/C API в отношении счетчиков ссылок лучше всего объяснять в терминах *владения ссылками*. Владение относится к ссылкам, никогда к объектам (объектами не владеют: они всегда разделяются). «Владение ссылкой» означает ответственность за вызов Py\_DECREF для нее, когда ссылка больше не нужна. Владение также может передаваться, что означает, что код, получающий владение ссылкой, становится ответственным за ее освобождение путем вызова [`Py_DECREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_DECREF) или [`Py_XDECREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_XDECREF), когда она больше не нужна, или за передачу этой ответственности дальше (обычно своему вызывающему). Когда функция передает владение ссылкой своему вызывающему, говорят, что вызывающий получает *новую* ссылку. Когда владение не передается, говорят, что вызывающий *заимствует* ссылку. Для [заимствованной ссылки](https://python-all.ru/3.16/glossary.html#term-borrowed-reference) ничего делать не нужно.479480И наоборот, когда вызывающая функция передает ссылку на объект, есть две возможности: функция *крадет* ссылку на объект или нет.481482*Кража ссылки* означает, что при передаче ссылки функции эта функция предполагает, что теперь она владеет этой ссылкой. Поскольку новый владелец может использовать `Py_DECREF()` по своему усмотрению, вызывающий не должен использовать эту ссылку после вызова.483484Немногие функции крадут ссылки; двумя заметными исключениями являются [`PyList_SetItem()`](https://python-all.ru/3.16/c-api/list.html#c.PyList_SetItem) и [`PyTuple_SetItem()`](https://python-all.ru/3.16/c-api/tuple.html#c.PyTuple_SetItem), которые крадут ссылку на элемент (но не на кортеж или список, в который помещается элемент!). Эти функции были спроектированы так, чтобы красть ссылку из-за распространенного идиоматического приема заполнения кортежа или списка только что созданными объектами; например, код для создания кортежа `(1, 2, "three")` может выглядеть так (пока забывая об обработке ошибок; лучший способ написать это показан ниже):485486```c487PyObject *t;488489t = PyTuple_New(3);490PyTuple_SetItem(t, 0, PyLong_FromLong(1L));491PyTuple_SetItem(t, 1, PyLong_FromLong(2L));492PyTuple_SetItem(t, 2, PyUnicode_FromString("three"));493```494495Здесь [`PyLong_FromLong()`](https://python-all.ru/3.16/c-api/long.html#c.PyLong_FromLong) возвращает новую ссылку, которая немедленно крадется [`PyTuple_SetItem()`](https://python-all.ru/3.16/c-api/tuple.html#c.PyTuple_SetItem). Если требуется продолжать использовать объект, хотя ссылка на него будет украдена, используйте [`Py_INCREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_INCREF), чтобы получить другую ссылку перед вызовом функции, крадущей ссылки.496497Кстати, [`PyTuple_SetItem()`](https://python-all.ru/3.16/c-api/tuple.html#c.PyTuple_SetItem) – это *единственный* способ задать элементы кортежа. [`PySequence_SetItem()`](https://python-all.ru/3.16/c-api/sequence.html#c.PySequence_SetItem) и [`PyObject_SetItem()`](https://python-all.ru/3.16/c-api/object.html#c.PyObject_SetItem) отказываются это делать, поскольку кортежи – неизменяемый тип данных. Используйте `PyTuple_SetItem()` только для кортежей, которые создаёте самостоятельно.498499Эквивалентный код для заполнения списка можно написать с помощью [`PyList_New()`](https://python-all.ru/3.16/c-api/list.html#c.PyList_New) и [`PyList_SetItem()`](https://python-all.ru/3.16/c-api/list.html#c.PyList_SetItem).500501Однако на практике эти способы создания и заполнения кортежа или списка используются редко. Существует универсальная функция [`Py_BuildValue()`](https://python-all.ru/3.16/c-api/arg.html#c.Py_BuildValue), которая может создавать большинство распространённых объектов из значений C, управляемая *строкой формата*. Например, два приведённых выше блока кода можно заменить следующим (который также выполняет проверку ошибок):502503```c504PyObject *tuple, *list;505506tuple = Py_BuildValue("(iis)", 1, 2, "three");507list = Py_BuildValue("[iis]", 1, 2, "three");508```509510Гораздо чаще [`PyObject_SetItem()`](https://python-all.ru/3.16/c-api/object.html#c.PyObject_SetItem) и подобные функции используются с элементами, ссылки на которые только заимствуются, например, с аргументами, переданными в функцию. В этом случае их поведение в отношении ссылок гораздо разумнее, поскольку не нужно получать новую ссылку только для того, чтобы отдать её («позволить её украсть»). Например, эта функция устанавливает все элементы списка (фактически любой изменяемой последовательности) в заданный элемент:511512```c513int514set_all(PyObject *target, PyObject *item)515{516 Py_ssize_t i, n;517518 n = PyObject_Length(target);519 if (n < 0)520 return -1;521 for (i = 0; i < n; i++) {522 PyObject *index = PyLong_FromSsize_t(i);523 if (!index)524 return -1;525 if (PyObject_SetItem(target, index, item) < 0) {526 Py_DECREF(index);527 return -1;528 }529 Py_DECREF(index);530 }531 return 0;532}533```534535Ситуация немного отличается для возвращаемых значений функций. Хотя передача ссылки большинству функций не меняет обязанности по владению этой ссылкой, многие функции, возвращающие ссылку на объект, передают владение ссылкой вызывающему. Причина проста: во многих случаях возвращаемый объект создаётся на лету, и полученная ссылка является единственной ссылкой на объект. Поэтому универсальные функции, возвращающие ссылки на объекты, такие как [`PyObject_GetItem()`](https://python-all.ru/3.16/c-api/object.html#c.PyObject_GetItem) и [`PySequence_GetItem()`](https://python-all.ru/3.16/c-api/sequence.html#c.PySequence_GetItem), всегда возвращают новую ссылку (вызывающий становится владельцем ссылки).536537Важно понимать, что владение ссылкой, возвращённой функцией, зависит только от того, какая функция вызывается – *оперение* (тип объекта, переданного в качестве аргумента функции) *не играет роли!* Таким образом, при извлечении элемента из списка с помощью [`PyList_GetItem()`](https://python-all.ru/3.16/c-api/list.html#c.PyList_GetItem) ссылка не переходит во владение – но при получении того же элемента из того же списка с помощью [`PySequence_GetItem()`](https://python-all.ru/3.16/c-api/sequence.html#c.PySequence_GetItem) (которая принимает точно такие же аргументы) возвращённая ссылка переходит во владение.538539Вот пример того, как можно написать функцию, вычисляющую сумму элементов списка целых чисел; один раз с помощью [`PyList_GetItem()`](https://python-all.ru/3.16/c-api/list.html#c.PyList_GetItem), и один раз с помощью [`PySequence_GetItem()`](https://python-all.ru/3.16/c-api/sequence.html#c.PySequence_GetItem).540541```c542long543sum_list(PyObject *list)544{545 Py_ssize_t i, n;546 long total = 0, value;547 PyObject *item;548549 n = PyList_Size(list);550 if (n < 0)551 return -1; /* Не список */552 for (i = 0; i < n; i++) {553 item = PyList_GetItem(list, i); /* Не может завершиться ошибкой */554 if (!PyLong_Check(item)) continue; /* Пропустить нецелые значения */555 value = PyLong_AsLong(item);556 if (value == -1 && PyErr_Occurred())557 /* Целое число слишком велико для C long, выход */558 return -1;559 total += value;560 }561 return total;562}563```564565```c566long567sum_sequence(PyObject *sequence)568{569 Py_ssize_t i, n;570 long total = 0, value;571 PyObject *item;572 n = PySequence_Length(sequence);573 if (n < 0)574 return -1; /* Не имеет длины */575 for (i = 0; i < n; i++) {576 item = PySequence_GetItem(sequence, i);577 if (item == NULL)578 return -1; /* Не последовательность или другая ошибка */579 if (PyLong_Check(item)) {580 value = PyLong_AsLong(item);581 Py_DECREF(item);582 if (value == -1 && PyErr_Occurred())583 /* Целое число слишком велико для C long, выход */584 return -1;585 total += value;586 }587 else {588 Py_DECREF(item); /* Отказ от владения ссылкой */589 }590 }591 return total;592}593```594595### Типы596597Существует ещё несколько типов данных, играющих важную роль в Python/C API; большинство из них – простые типы C, такие как int, long, double и char\*. Некоторые структурные типы используются для описания статических таблиц, в которых перечисляются функции, экспортируемые модулем, или атрибуты данных нового типа объекта, а другой тип используется для описания значения комплексного числа. Они будут рассмотрены вместе с функциями, которые их используют.598599#### `type Py_ssize_t`600601*Часть [Stable ABI](https://python-all.ru/3.16/c-api/stable.html#stable).*602603Знаковый целочисленный тип, такой что `sizeof(Py_ssize_t) == sizeof(size_t)`. C99 не определяет такой тип напрямую (size\_t – это беззнаковый целочисленный тип). Подробнее см. [**PEP 353**](https://python-all.ru/3.16/c-api/intro.html). `PY_SSIZE_T_MAX` – это наибольшее положительное значение типа [`Py_ssize_t`](https://python-all.ru/3.16/c-api/intro.html#c.Py_ssize_t).604605## Исключения606607Программисту на Python требуется обрабатывать исключения только в тех случаях, когда необходима специфическая обработка ошибок; необработанные исключения автоматически передаются вызывающему, затем вызывающему вызывающего и так далее, пока не достигнут интерпретатора верхнего уровня, где они сообщаются пользователю вместе с трассировкой стека.608609Однако для C-программистов проверка ошибок всегда должна быть явной. Все функции Python/C API могут вызывать исключения, если в документации функции не указано иное. В общем случае, когда функция обнаруживает ошибку, она устанавливает исключение, отбрасывает все принадлежащие ей ссылки на объекты и возвращает индикатор ошибки. Если не задокументировано иное, этот индикатор – либо `NULL`, либо `-1`, в зависимости от типа возвращаемого значения функции. Некоторые функции возвращают логический результат true/false, где false указывает на ошибку. Очень немногие функции не возвращают явного индикатора ошибки или имеют неоднозначное возвращаемое значение и требуют явной проверки на ошибки с помощью [`PyErr_Occurred()`](https://python-all.ru/3.16/c-api/exceptions.html#c.PyErr_Occurred). Такие исключения всегда явно документируются.610611Состояние исключения хранится в памяти, привязанной к потоку (это эквивалентно использованию глобальной памяти в однопоточном приложении). Поток может находиться в одном из двух состояний: произошло исключение или нет. Функция [`PyErr_Occurred()`](https://python-all.ru/3.16/c-api/exceptions.html#c.PyErr_Occurred) может использоваться для проверки этого: она возвращает заимствованную ссылку на объект типа исключения, если произошло исключение, и `NULL` в противном случае. Существует ряд функций для установки состояния исключения: [`PyErr_SetString()`](https://python-all.ru/3.16/c-api/exceptions.html#c.PyErr_SetString) является наиболее распространённой (хотя и не самой общей) функцией для установки состояния исключения, а [`PyErr_Clear()`](https://python-all.ru/3.16/c-api/exceptions.html#c.PyErr_Clear) очищает состояние исключения.612613Полное состояние исключения состоит из трёх объектов (все они могут быть `NULL`): типа исключения, соответствующего значения исключения и трассировки стека. Они имеют тот же смысл, что и результат Python `sys.exc_info()`; однако они не одно и то же: объекты Python представляют последнее исключение, обрабатываемое оператором [`try`](https://python-all.ru/3.16/reference/compound_stmts.html#try) … [`except`](https://python-all.ru/3.16/reference/compound_stmts.html#except), в то время как состояние исключения на уровне C существует только пока исключение передаётся между C-функциями, пока не достигнет основного цикла интерпретатора байт-кода Python, который заботится о его передаче в `sys.exc_info()` и подобные.614615Обратите внимание, что начиная с Python 1.5 предпочтительным потокобезопасным способом доступа к состоянию исключения из кода Python является вызов функции [`sys.exc_info()`](https://python-all.ru/3.16/library/sys.html#sys.exc_info), которая возвращает состояние исключения для текущего потока в коде Python. Кроме того, семантика обоих способов доступа к состоянию исключения была изменена таким образом, что функция, перехватывающая исключение, сохраняет и восстанавливает состояние исключения своего потока, чтобы сохранить состояние исключения вызывающей функции. Это предотвращает распространённые ошибки в коде обработки исключений, вызванные тем, что безобидная на вид функция перезаписывает обрабатываемое исключение; это также уменьшает часто нежелательное продление времени жизни объектов, на которые ссылаются кадры стека в трассировке.616617В качестве общего принципа: функция, которая вызывает другую функцию для выполнения некоторой задачи, должна проверять, вызвала ли вызываемая функция исключение, и если да, передавать состояние исключения своему вызывающему. Она должна отбрасывать все принадлежащие ей ссылки на объекты и возвращать индикатор ошибки, но *не* должна устанавливать другое исключение – это перезапишет только что вызванное исключение и приведёт к потере важной информации о точной причине ошибки.618619Простой пример обнаружения исключений и их передачи показан в примере `sum_sequence()` выше. Так получилось, что этому примеру не нужно очищать принадлежащие ссылки при обнаружении ошибки. Следующая примерная функция показывает некоторую очистку при ошибке. Сначала, чтобы напомнить о преимуществах Python, приведён эквивалентный код на Python:620621```c622def incr_item(dict, key):623 try:624 item = dict[key]625 except KeyError:626 item = 0627 dict[key] = item + 1628```629630А вот соответствующий код на C во всей своей красе:631632```c633int634incr_item(PyObject *dict, PyObject *key)635{636 /* Все объекты инициализированы в NULL для Py_XDECREF */637 PyObject *item = NULL, *const_one = NULL, *incremented_item = NULL;638 int rv = -1; /* Возвращаемое значение инициализировано как -1 (ошибка) */639640 item = PyObject_GetItem(dict, key);641 if (item == NULL) {642 /* Обрабатывать только KeyError: */643 if (!PyErr_ExceptionMatches(PyExc_KeyError))644 goto error;645646 /* Очистить ошибку и использовать ноль: */647 PyErr_Clear();648 item = PyLong_FromLong(0L);649 if (item == NULL)650 goto error;651 }652 const_one = PyLong_FromLong(1L);653 if (const_one == NULL)654 goto error;655656 incremented_item = PyNumber_Add(item, const_one);657 if (incremented_item == NULL)658 goto error;659660 if (PyObject_SetItem(dict, key, incremented_item) < 0)661 goto error;662 rv = 0; /* Успех */663 /* Продолжить с кодом очистки */664665 error:666 /* Код очистки, общий для путей успеха и ошибки */667668 /* Используйте Py_XDECREF() для игнорирования NULL-ссылок */669 Py_XDECREF(item);670 Py_XDECREF(const_one);671 Py_XDECREF(incremented_item);672673 return rv; /* -1 для ошибки, 0 для успеха */674}675```676677Этот пример представляет собой одобренное использование оператора `goto` в C! Он иллюстрирует использование [`PyErr_ExceptionMatches()`](https://python-all.ru/3.16/c-api/exceptions.html#c.PyErr_ExceptionMatches) и [`PyErr_Clear()`](https://python-all.ru/3.16/c-api/exceptions.html#c.PyErr_Clear) для обработки конкретных исключений, а также использование [`Py_XDECREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_XDECREF) для освобождения принадлежащих ссылок, которые могут быть `NULL` (обратите внимание на `'X'` в имени; [`Py_DECREF()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_DECREF) аварийно завершится при столкновении с `NULL` ссылкой). Важно, чтобы переменные, используемые для хранения принадлежащих ссылок, были инициализированы значением `NULL` для корректной работы; аналогично, предлагаемое возвращаемое значение инициализируется как `-1` (неудача) и устанавливается в успех только после того, как последний вызов завершится успешно.678679## Встраивание Python680681Единственная важная задача, о которой должны беспокоиться только разработчики, встраивающие интерпретатор Python (в отличие от разработчиков расширений), – это инициализация и, возможно, финализация интерпретатора Python. Большинство функций интерпретатора могут использоваться только после его инициализации.682683Основная функция инициализации – [`Py_Initialize()`](https://python-all.ru/3.16/c-api/interp-lifecycle.html#c.Py_Initialize). Она инициализирует таблицу загруженных модулей и создаёт фундаментальные модули [`builtins`](https://python-all.ru/3.16/library/builtins.html#module-builtins), [`__main__`](https://python-all.ru/3.16/library/__main__.html#module-__main__) и [`sys`](https://python-all.ru/3.16/library/sys.html#module-sys). Также она инициализирует путь поиска модулей (`sys.path`).684685[`Py_Initialize()`](https://python-all.ru/3.16/c-api/interp-lifecycle.html#c.Py_Initialize) не устанавливает «список аргументов сценария» (`sys.argv`). Если эта переменная необходима коду Python, который будет выполняться позже, необходимо установить [`PyConfig.argv`](https://python-all.ru/3.16/c-api/init_config.html#c.PyConfig.argv) и [`PyConfig.parse_argv`](https://python-all.ru/3.16/c-api/init_config.html#c.PyConfig.parse_argv): см. [Python Initialization Configuration](https://python-all.ru/3.16/c-api/init_config.html#init-config).686687В большинстве систем (в частности, в Unix и Windows, хотя детали несколько различаются) [`Py_Initialize()`](https://python-all.ru/3.16/c-api/interp-lifecycle.html#c.Py_Initialize) вычисляет путь поиска модулей, основываясь на наилучшем предположении о местоположении исполняемого файла стандартного интерпретатора Python, предполагая, что библиотека Python находится в фиксированном месте относительно исполняемого файла интерпретатора Python. В частности, он ищет каталог с именем `lib/pythonX.Y` относительно родительского каталога, где находится исполняемый файл с именем `python` в пути поиска команд оболочки (переменная окружения `PATH`).688689Например, если исполняемый файл Python находится в `/usr/local/bin/python`, то будет предполагаться, что библиотеки находятся в `/usr/local/lib/pythonX.Y`. (Фактически, этот конкретный путь также является «запасным» местоположением, используемым, когда исполняемый файл с именем `python` не найден вдоль `PATH`.) Пользователь может переопределить это поведение, установив переменную окружения [`PYTHONHOME`](https://python-all.ru/3.16/using/cmdline.html#envvar-PYTHONHOME), или вставить дополнительные каталоги в начало стандартного пути, установив [`PYTHONPATH`](https://python-all.ru/3.16/using/cmdline.html#envvar-PYTHONPATH).690691Встраивающее приложение может управлять поиском, установив [`PyConfig.program_name`](https://python-all.ru/3.16/c-api/init_config.html#c.PyConfig.program_name) *перед* вызовом [`Py_InitializeFromConfig()`](https://python-all.ru/3.16/c-api/interp-lifecycle.html#c.Py_InitializeFromConfig). Обратите внимание, что [`PYTHONHOME`](https://python-all.ru/3.16/using/cmdline.html#envvar-PYTHONHOME) по-прежнему переопределяет это, а [`PYTHONPATH`](https://python-all.ru/3.16/using/cmdline.html#envvar-PYTHONPATH) всё ещё вставляется в начало стандартного пути.692693Иногда бывает желательно «деинициализировать» Python. Например, приложение может захотеть начать заново (сделать ещё один вызов [`Py_Initialize()`](https://python-all.ru/3.16/c-api/interp-lifecycle.html#c.Py_Initialize)) или просто завершить использование Python и освободить память, выделенную Python. Это можно сделать, вызвав [`Py_FinalizeEx()`](https://python-all.ru/3.16/c-api/interp-lifecycle.html#c.Py_FinalizeEx). Функция [`Py_IsInitialized()`](https://python-all.ru/3.16/c-api/interp-lifecycle.html#c.Py_IsInitialized) возвращает true, если Python в настоящее время находится в инициализированном состоянии. Дополнительная информация об этих функциях приведена в следующей главе. Обратите внимание, что `Py_FinalizeEx()` *не* освобождает всю память, выделенную интерпретатором Python, например, память, выделенная модулями расширения, в настоящее время не может быть освобождена.694695## Отладочные сборки696697Python может быть собран с несколькими макросами для включения дополнительных проверок интерпретатора и модулей расширения. Эти проверки, как правило, добавляют значительные накладные расходы во время выполнения, поэтому они не включены по умолчанию.698699Полный список различных типов отладочных сборок находится в файле `Misc/SpecialBuilds.txt` в дистрибутиве исходного кода Python. Доступны сборки, поддерживающие трассировку счётчиков ссылок, отладку распределителя памяти или низкоуровневое профилирование основного цикла интерпретатора. В оставшейся части этого раздела будут описаны только наиболее часто используемые сборки.700701#### `Py_DEBUG`702703Компиляция интерпретатора с определённым макросом `Py_DEBUG` даёт то, что обычно называют [отладочной сборкой Python](https://python-all.ru/3.16/using/configure.html#debug-build).704705В Unix `Py_DEBUG` можно включить, добавив [`--with-pydebug`](https://python-all.ru/3.16/using/configure.html#cmdoption-with-pydebug) к команде `./configure`. При этом также отключается оптимизация компилятора.706707В Windows выбор отладочной сборки (например, передача опции [`-d`](https://python-all.ru/3.16/using/cmdline.html#cmdoption-d) `PCbuild/build.bat`) автоматически включает `Py_DEBUG`. Кроме того, наличие неспецифичного для Python макроса `_DEBUG`, если он определён компилятором, также неявно включает `Py_DEBUG`.708709Помимо отладки подсчёта ссылок, описанной ниже, выполняются дополнительные проверки. Подробнее см. [Python Debug Build](https://python-all.ru/3.16/using/configure.html#debug-build).710711Определение `Py_TRACE_REFS` включает отслеживание ссылок (см. [`configure --with-trace-refs option`](https://python-all.ru/3.16/using/configure.html#cmdoption-with-trace-refs)). При определении ведётся циклический двусвязный список активных объектов с помощью добавления двух дополнительных полей к каждому [`PyObject`](https://python-all.ru/3.16/c-api/structures.html#c.PyObject). Также отслеживаются общие выделения памяти. При выходе печатаются все существующие ссылки. (В интерактивном режиме это происходит после каждого выполненного интерпретатором оператора.)712713См. `Misc/SpecialBuilds.txt` в дистрибутиве исходных текстов Python для получения более подробной информации.714715## Рекомендуемые сторонние инструменты716717Следующие сторонние инструменты предлагают как более простые, так и более сложные подходы к созданию расширений для Python на C, C++ и Rust:718719- [Cython](https://python-all.ru/3.16/c-api/intro.html)720- [cffi](https://python-all.ru/3.16/c-api/intro.html)721- [HPy](https://python-all.ru/3.16/c-api/intro.html)722- [nanobind](https://python-all.ru/3.16/c-api/intro.html) (C++)723- [Numba](https://python-all.ru/3.16/c-api/intro.html)724- [pybind11](https://python-all.ru/3.16/c-api/intro.html) (C++)725- [PyO3](https://python-all.ru/3.16/c-api/intro.html) (Rust)726- [SWIG](https://python-all.ru/3.16/c-api/intro.html)727728Использование таких инструментов помогает избежать написания кода, жёстко привязанного к конкретной версии CPython, избежать ошибок подсчёта ссылок и сосредоточиться больше на собственном коде, а не на использовании API CPython. В целом, новые версии Python поддерживаются путём обновления инструмента, и ваш код часто будет автоматически использовать более новые и эффективные API. Некоторые инструменты также поддерживают компиляцию для других реализаций Python из единого набора исходников.729730Эти проекты не поддерживаются теми же людьми, которые поддерживают Python, и вопросы необходимо направлять непосредственно проектам. Не забудьте проверить, что проект всё ещё поддерживается, так как приведённый выше список может устареть.731732> **См. также**733>734> **[Python Packaging User Guide: Binary Extensions](https://python-all.ru/3.16/c-api/intro.html)**735>736> Руководство пользователя по упаковке Python (Python Packaging User Guide) не только охватывает несколько доступных инструментов, упрощающих создание двоичных расширений, но и обсуждает различные причины, по которым создание модуля расширения может быть желательным в первую очередь.737