> **Источник:** https://python-all.ru/3.16/c-api/code.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# Объекты кода

Объекты кода – это низкоуровневая деталь реализации CPython. Каждый из них представляет блок исполняемого кода, который ещё не привязан к функции.

#### `type PyCodeObject`

C-структура объектов, используемых для описания объектов кода. Поля этого типа могут быть изменены в любое время.

#### `PyTypeObject PyCode_Type`

Это экземпляр [`PyTypeObject`](https://python-all.ru/3.16/c-api/type.html#c.PyTypeObject), представляющий [объект кода](https://python-all.ru/3.16/reference/datamodel.html#code-objects) Python.

#### `int PyCode_Check(PyObject *co)`

Возвращает true, если *co* является [объектом кода](https://python-all.ru/3.16/reference/datamodel.html#code-objects). Эта функция всегда выполняется успешно.

#### `Py_ssize_t PyCode_GetNumFree(PyCodeObject *co)`

Возвращает количество [свободных (замыкающих) переменных](https://python-all.ru/3.16/glossary.html#term-closure-variable) в объекте кода.

#### `int PyUnstable_Code_GetFirstFree(PyCodeObject *co)`

> *Это [нестабильное API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Оно может измениться без предупреждения в минорных выпусках.*

Возвращает позицию первой [свободной (замыкающей) переменной](https://python-all.ru/3.16/glossary.html#term-closure-variable) в объекте кода.

Изменено в версии 3.13: Переименовано из `PyCode_GetFirstFree` в рамках [нестабильного C API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Старое имя устарело, но останется доступным до следующего изменения сигнатуры.

#### `PyCodeObject *PyUnstable_Code_New(int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)`

> *Это [нестабильное API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Оно может измениться без предупреждения в минорных выпусках.*

Возвращает новый объект кода. Если нужен фиктивный объект кода для создания фрейма, используйте [`PyCode_NewEmpty()`](https://python-all.ru/3.16/c-api/code.html#c.PyCode_NewEmpty).

Поскольку определение байт-кода часто меняется, прямой вызов [`PyUnstable_Code_New()`](https://python-all.ru/3.16/c-api/code.html#c.PyUnstable_Code_New) может привязать к конкретной версии Python.

Многочисленные аргументы этой функции сложным образом взаимозависимы, поэтому незначительные изменения значений могут привести к некорректному исполнению или сбою виртуальной машины. Используйте эту функцию с крайней осторожностью.

Изменено в версии 3.11: Добавлены параметры `qualname` и `exceptiontable`.

Изменено в версии 3.12: Переименовано из `PyCode_New` в рамках [нестабильного C API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Старое имя устарело, но останется доступным до следующего изменения сигнатуры.

#### `PyCodeObject *PyUnstable_Code_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)`

> *Это [нестабильное API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Оно может измениться без предупреждения в минорных выпусках.*

Аналогично [`PyUnstable_Code_New()`](https://python-all.ru/3.16/c-api/code.html#c.PyUnstable_Code_New), но с дополнительным параметром “posonlyargcount” для позиционных аргументов. Те же предостережения, что и для `PyUnstable_Code_New`, применимы к этой функции.

Добавлено в версии 3.8: как `PyCode_NewWithPosOnlyArgs`

Изменено в версии 3.11: Добавлены параметры `qualname` и `exceptiontable`.

Изменено в версии 3.12: Переименован в `PyUnstable_Code_NewWithPosOnlyArgs`. Старое имя устарело, но останется доступным до следующего изменения сигнатуры.

#### `PyCodeObject *PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)`

*Возвращаемое значение: новая ссылка.*

Возвращает новый пустой объект кода с указанными именем файла, именем функции и номером первой строки. Полученный объект кода вызовет `Exception` при выполнении.

#### `int PyCode_Addr2Line(PyCodeObject *co, int byte_offset)`

Возвращает номер строки инструкции, которая начинается до или на `byte_offset` и заканчивается после него. Если нужен просто номер строки фрейма, используйте [`PyFrame_GetLineNumber()`](https://python-all.ru/3.16/c-api/frame.html#c.PyFrame_GetLineNumber).

Для эффективного перебора номеров строк в объекте кода используйте [**API, описанный в PEP 626**](https://python-all.ru/3.16/c-api/code.html).

#### `int PyCode_Addr2Location(PyObject *co, int byte_offset, int *start_line, int *start_column, int *end_line, int *end_column)`

Устанавливает переданные указатели `int` на номера строки и столбца исходного кода для инструкции по адресу `byte_offset`. Устанавливает значение `0`, если информация для какого-либо элемента недоступна.

Возвращает `1` при успехе функции и 0 в противном случае.

Добавлено в версии 3.11.

#### `PyObject *PyCode_GetCode(PyCodeObject *co)`

Эквивалент кода Python `getattr(co, 'co_code')`. Возвращает сильную ссылку на [`PyBytesObject`](https://python-all.ru/3.16/c-api/bytes.html#c.PyBytesObject), представляющий байт-код в объекте кода. В случае ошибки возвращается `NULL` и возбуждается исключение.

Этот `PyBytesObject` может быть создан интерпретатором по требованию и не обязательно представляет байт-код, который действительно выполняется CPython. Основное назначение этой функции – отладчики и профилировщики.

Добавлено в версии 3.11.

#### `PyObject *PyCode_GetVarnames(PyCodeObject *co)`

Эквивалент кода Python `getattr(co, 'co_varnames')`. Возвращает новую ссылку на [`PyTupleObject`](https://python-all.ru/3.16/c-api/tuple.html#c.PyTupleObject), содержащий имена локальных переменных. В случае ошибки возвращается `NULL` и возбуждается исключение.

Добавлено в версии 3.11.

#### `PyObject *PyCode_GetCellvars(PyCodeObject *co)`

Эквивалент кода Python `getattr(co, 'co_cellvars')`. Возвращает новую ссылку на [`PyTupleObject`](https://python-all.ru/3.16/c-api/tuple.html#c.PyTupleObject), содержащий имена локальных переменных, на которые ссылаются вложенные функции. В случае ошибки возвращается `NULL` и возбуждается исключение.

Добавлено в версии 3.11.

#### `PyObject *PyCode_GetFreevars(PyCodeObject *co)`

Эквивалент кода Python `getattr(co, 'co_freevars')`. Возвращает новую ссылку на [`PyTupleObject`](https://python-all.ru/3.16/c-api/tuple.html#c.PyTupleObject), содержащий имена [свободных (замыкающих) переменных](https://python-all.ru/3.16/glossary.html#term-closure-variable). В случае ошибки возвращается `NULL` и возбуждается исключение.

Добавлено в версии 3.12.

#### `int PyCode_AddWatcher(PyCode_WatchCallback callback)`

Регистрирует *колбэк* как наблюдатель за объектами кода для текущего интерпретатора. Возвращает идентификатор, который можно передать в [`PyCode_ClearWatcher()`](https://python-all.ru/3.16/c-api/code.html#c.PyCode_ClearWatcher). В случае ошибки (например, нет свободных идентификаторов наблюдателей) возвращает `-1` и устанавливает исключение.

Добавлено в версии 3.12.

#### `int PyCode_ClearWatcher(int watcher_id)`

Удаляет наблюдатель, заданный идентификатором *watcher\_id*, ранее полученным от [`PyCode_AddWatcher()`](https://python-all.ru/3.16/c-api/code.html#c.PyCode_AddWatcher) для текущего интерпретатора. Возвращает `0` при успехе или `-1` с установкой исключения при ошибке (например, если указанный *watcher\_id* никогда не был зарегистрирован).

Добавлено в версии 3.12.

#### `type PyCodeEvent`

Перечисление возможных событий наблюдателя объекта кода: - `PY_CODE_EVENT_CREATE` - `PY_CODE_EVENT_DESTROY`

Добавлено в версии 3.12.

#### `typedef int (*PyCode_WatchCallback)(PyCodeEvent event, PyCodeObject *co)`

Тип функции обратного вызова наблюдателя объекта кода.

Если *event* равно `PY_CODE_EVENT_CREATE`, то обратный вызов вызывается после полной инициализации *co*. В противном случае обратный вызов вызывается до того, как произойдет уничтожение *co*, так что можно проверить предыдущее состояние *co*.

Если *event* равно `PY_CODE_EVENT_DESTROY`, то получение ссылки в обратном вызове на объект кода, который должен быть уничтожен, воскресит его и предотвратит его освобождение в данный момент. Когда воскрешенный объект будет уничтожен позже, все активные на тот момент обратные вызовы наблюдателей будут вызваны снова.

Пользователи этого API не должны полагаться на внутренние детали реализации среды выполнения. Такие детали могут включать, но не ограничиваясь, точный порядок и время создания и уничтожения объектов кода. Хотя изменения этих деталей могут привести к различиям, наблюдаемым наблюдателями (включая то, вызывается ли обратный вызов или нет), это не меняет семантику выполняемого кода Python.

Если обратный вызов устанавливает исключение, он должен вернуть `-1`; это исключение будет выведено как неподнимаемое исключение с помощью [`PyErr_WriteUnraisable()`](https://python-all.ru/3.16/c-api/exceptions.html#c.PyErr_WriteUnraisable). В противном случае он должен вернуть `0`.

На момент входа в обратный вызов уже может быть установлено отложенное исключение. В этом случае обратный вызов должен вернуть `0`, оставив то же исключение установленным. Это означает, что обратный вызов не может вызывать никакой другой API, который может установить исключение, если только он сначала не сохранит и не очистит состояние исключения, а затем не восстановит его перед возвратом.

Добавлено в версии 3.12.

#### `PyObject *PyCode_Optimize(PyObject *code, PyObject *consts, PyObject *names, PyObject *lnotab_obj)`

Это функция, которая ничего не делает.

До Python 3.10 эта функция выполняла базовые оптимизации объекта кода.

Изменено в версии 3.10: Теперь эта функция ничего не делает.

[Мягкое устаревание](https://python-all.ru/3.16/glossary.html#term-soft-deprecated) начиная с версии 3.13.

# Флаги объекта кода

Объекты кода содержат битовое поле флагов, которое можно получить как атрибут Python [`co_flags`](https://python-all.ru/3.16/reference/datamodel.html#codeobject.co_flags) (например, используя [`PyObject_GetAttrString()`](https://python-all.ru/3.16/c-api/object.html#c.PyObject_GetAttrString)), и установить с помощью аргумента *flags* в [`PyUnstable_Code_New()`](https://python-all.ru/3.16/c-api/code.html#c.PyUnstable_Code_New) и аналогичных функциях.

Флаги, имена которых начинаются с `CO_FUTURE_`, соответствуют функциям, обычно выбираемым с помощью [операторов будущего](https://python-all.ru/3.16/reference/simple_stmts.html#future). Эти флаги можно использовать в [`PyCompilerFlags.cf_flags`](https://python-all.ru/3.16/c-api/veryhigh.html#c.PyCompilerFlags.cf_flags). Обратите внимание, что многие флаги `CO_FUTURE_` являются обязательными в текущих версиях Python, и их установка не имеет эффекта.

Доступны следующие флаги. Об их значении см. в документации их аналогов из Python по ссылкам.

| Флаг | Значение |
| --- | --- |
| CO\_OPTIMIZED | [`inspect.CO_OPTIMIZED`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_OPTIMIZED) |
| CO\_NEWLOCALS | [`inspect.CO_NEWLOCALS`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_NEWLOCALS) |
| CO\_VARARGS | [`inspect.CO_VARARGS`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_VARARGS) |
| CO\_VARKEYWORDS | [`inspect.CO_VARKEYWORDS`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_VARKEYWORDS) |
| CO\_NESTED | [`inspect.CO_NESTED`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_NESTED) |
| CO\_GENERATOR | [`inspect.CO_GENERATOR`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_GENERATOR) |
| CO\_COROUTINE | [`inspect.CO_COROUTINE`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_COROUTINE) |
| CO\_ITERABLE\_COROUTINE | [`inspect.CO_ITERABLE_COROUTINE`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_ITERABLE_COROUTINE) |
| CO\_ASYNC\_GENERATOR | [`inspect.CO_ASYNC_GENERATOR`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_ASYNC_GENERATOR) |
| CO\_HAS\_DOCSTRING | [`inspect.CO_HAS_DOCSTRING`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_HAS_DOCSTRING) |
| CO\_METHOD | [`inspect.CO_METHOD`](https://python-all.ru/3.16/library/inspect.html#inspect.CO_METHOD) |
| CO\_FUTURE\_DIVISION | не имеет эффекта ([`__future__.division`](https://python-all.ru/3.16/library/__future__.html#future__.division)) |
| CO\_FUTURE\_ABSOLUTE\_IMPORT | не имеет эффекта ([`__future__.absolute_import`](https://python-all.ru/3.16/library/__future__.html#future__.absolute_import)) |
| CO\_FUTURE\_WITH\_STATEMENT | не имеет эффекта ([`__future__.with_statement`](https://python-all.ru/3.16/library/__future__.html#future__.with_statement)) |
| CO\_FUTURE\_PRINT\_FUNCTION | не имеет эффекта ([`__future__.print_function`](https://python-all.ru/3.16/library/__future__.html#future__.print_function)) |
| CO\_FUTURE\_UNICODE\_LITERALS | не имеет эффекта ([`__future__.unicode_literals`](https://python-all.ru/3.16/library/__future__.html#future__.unicode_literals)) |
| CO\_FUTURE\_GENERATOR\_STOP | не имеет эффекта ([`__future__.generator_stop`](https://python-all.ru/3.16/library/__future__.html#future__.generator_stop)) |
| CO\_FUTURE\_ANNOTATIONS | [`__future__.annotations`](https://python-all.ru/3.16/library/__future__.html#future__.annotations) |

# Дополнительная информация

Для поддержки низкоуровневых расширений механизма вычисления кадров, таких как внешние JIT-компиляторы, к объектам кода можно прикреплять произвольные дополнительные данные.

Эти функции относятся к нестабильному уровню C API: данная функциональность является деталью реализации CPython, и API может измениться без предупреждения об устаревании.

#### `Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free)`

> *Это [нестабильное API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Оно может меняться без предупреждения в минорных версиях.*

Возвращает новое непрозрачное значение индекса, используемое для добавления данных к объектам кода.

Обычно эту функцию вызывают один раз (на каждый интерпретатор) и используют полученный результат с `PyCode_GetExtra` и `PyCode_SetExtra` для управления данными на отдельных объектах кода.

Если *free* не равен `NULL`: при освобождении объекта кода будет вызван *free* для данных, не являющихся `NULL`, хранящихся под новым индексом. Используйте [`Py_DecRef()`](https://python-all.ru/3.16/c-api/refcounting.html#c.Py_DecRef) при хранении [`PyObject`](https://python-all.ru/3.16/c-api/structures.html#c.PyObject).

Добавлено в версии 3.6: как `_PyEval_RequestCodeExtraIndex`

Изменено в версии 3.12: Переименовано в `PyUnstable_Eval_RequestCodeExtraIndex`. Старое приватное имя устарело, но будет доступно до изменения API.

#### `int PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra)`

> *Это [нестабильное API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Оно может меняться без предупреждения в минорных версиях.*

Устанавливает *extra* в дополнительные данные, хранящиеся по указанному индексу. Возвращает 0 в случае успеха. В случае ошибки устанавливает исключение и возвращает -1.

Если по индексу не было установлено никаких данных, устанавливает *extra* в `NULL` и возвращает 0 без установки исключения.

Добавлено в версии 3.6: как `_PyCode_GetExtra`

Изменено в версии 3.12: Переименовано в `PyUnstable_Code_GetExtra`. Старое приватное имя устарело, но будет доступно до изменения API.

#### `int PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra)`

> *Это [нестабильное API](https://python-all.ru/3.16/c-api/stable.html#unstable-c-api). Оно может меняться без предупреждения в минорных версиях.*

Устанавливает дополнительные данные, хранящиеся по указанному индексу, в *extra*. Возвращает 0 в случае успеха. В случае ошибки устанавливает исключение и возвращает -1.

Добавлено в версии 3.6: как `_PyCode_SetExtra`

Изменено в версии 3.12: Переименовано в `PyUnstable_Code_SetExtra`. Старое приватное имя устарело, но будет доступно до изменения API.
