init.md
1> **Источник:** https://python-all.ru/2.7/c-api/init.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Инициализация, финализация и потоки89## Инициализация и завершение работы интерпретатора1011#### `void Py_Initialize()`1213Инициализирует интерпретатор Python. В приложении, встраивающем Python, эта функция должна вызываться до использования любых других функций Python/C API; за исключением [`Py_SetProgramName()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetProgramName), [`Py_SetPythonHome()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetPythonHome), [`PyEval_InitThreads()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_InitThreads), [`PyEval_ReleaseLock()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_ReleaseLock) и [`PyEval_AcquireLock()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_AcquireLock). Она инициализирует таблицу загруженных модулей (`sys.modules`) и создаёт фундаментальные модули [`__builtin__`](https://python-all.ru/2.7/library/__builtin__.html#module-__builtin__), [`__main__`](https://python-all.ru/2.7/library/__main__.html#module-__main__) и [`sys`](https://python-all.ru/2.7/library/sys.html#module-sys). Также она инициализирует путь поиска модулей (`sys.path`). Она не устанавливает `sys.argv`; для этого используйте [`PySys_SetArgvEx()`](https://python-all.ru/2.7/c-api/init.html#c.PySys_SetArgvEx). При повторном вызове (без предварительного вызова [`Py_Finalize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Finalize)) она ничего не делает. Возвращаемого значения нет; если инициализация завершается неудачей, это фатальная ошибка.1415#### `void Py_InitializeEx(int initsigs)`1617Эта функция работает как [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize), если *initsigs* равно `1`. Если *initsigs* равно `0`, она пропускает регистрацию обработчиков сигналов при инициализации, что может быть полезно при встраивании Python.1819Новое в версии 2.4.2021#### `int Py_IsInitialized()`2223Возвращает true (ненулевое значение), если интерпретатор Python был инициализирован, и false (ноль), если нет. После вызова [`Py_Finalize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Finalize) функция возвращает false до тех пор, пока не будет снова вызвана [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize).2425#### `void Py_Finalize()`2627Отменяет всю инициализацию, выполненную с помощью [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize), и последующее использование функций Python/C API, а также уничтожает все подынтерпретаторы (см. [`Py_NewInterpreter()`](https://python-all.ru/2.7/c-api/init.html#c.Py_NewInterpreter) ниже), которые были созданы и ещё не уничтожены после последнего вызова [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize). В идеале это освобождает всю память, выделенную интерпретатором Python. При повторном вызове (без предварительного вызова [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize)) функция ничего не делает. Возвращаемого значения нет; ошибки в процессе финализации игнорируются.2829Эта функция предусмотрена по ряду причин. Встраивающее приложение может захотеть перезапустить Python без перезапуска самого приложения. Приложение, загрузившее интерпретатор Python из динамически загружаемой библиотеки (или DLL), может захотеть освободить всю память, выделенную Python, перед выгрузкой DLL. В процессе поиска утечек памяти в приложении разработчик может захотеть освободить всю память, выделенную Python, перед выходом из приложения.3031**Ошибки и предостережения:** Уничтожение модулей и объектов в модулях происходит в случайном порядке; из-за этого деструкторы (методы [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__)) могут давать сбой, если они зависят от других объектов (даже функций) или модулей. Динамически загруженные модули расширений, загруженные Python, не выгружаются. Небольшие объёмы памяти, выделенные интерпретатором Python, могут не освобождаться (если вы обнаружили утечку, сообщите о ней). Память, связанная циклическими ссылками между объектами, не освобождается. Некоторая память, выделенная модулями расширений, может не освобождаться. Некоторые расширения могут работать неправильно, если их процедура инициализации вызывается более одного раза; это может произойти, если приложение вызывает [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize) и [`Py_Finalize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Finalize) более одного раза.3233## Общепроцессные параметры3435#### `void Py_SetProgramName(char *name)`3637Эту функцию следует вызывать перед первым вызовом [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize), если она вообще вызывается. Она сообщает интерпретатору значение аргумента `argv[0]` функции `main()` программы. Это используется [`Py_GetPath()`](https://python-all.ru/2.7/c-api/init.html#c.Py_GetPath) и некоторыми другими функциями ниже для поиска библиотек времени выполнения Python относительно исполняемого файла интерпретатора. Значение по умолчанию – `'python'`. Аргумент должен указывать на нуль-терминированную строку символов в статической памяти, содержимое которой не изменится на время выполнения программы. Никакой код в интерпретаторе Python не изменит содержимое этой памяти.3839#### `char* Py_GetProgramName()`4041Возвращает имя программы, установленное с помощью [`Py_SetProgramName()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetProgramName), или значение по умолчанию. Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение.4243#### `char* Py_GetPrefix()`4445Возвращает *префикс* для установленных платформонезависимых файлов. Он определяется по ряду сложных правил из имени программы, установленного с помощью [`Py_SetProgramName()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetProgramName), и некоторых переменных окружения; например, если имя программы – `'/usr/local/bin/python'`, префикс – `'/usr/local'`. Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение. Это соответствует переменной **prefix** в корневом `Makefile` и аргументу `--prefix` сценария **configure** во время сборки. Значение доступно в коде Python как `sys.prefix`. Полезен только в Unix. Смотрите также следующую функцию.4647#### `char* Py_GetExecPrefix()`4849Возвращает *exec-prefix* для установленных *зависящих от платформы* файлов. Это значение вычисляется по ряду сложных правил на основе имени программы, заданного с помощью [`Py_SetProgramName()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetProgramName), и некоторых переменных окружения; например, если имя программы – `'/usr/local/bin/python'`, то exec-prefix – `'/usr/local'`. Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение. Это соответствует переменной **exec\_prefix** в верхнеуровневом `Makefile` и аргументу `--exec-prefix` сценария **configure** во время сборки. Значение доступно коду Python как `sys.exec_prefix`. Это имеет смысл только в Unix.5051Контекст: exec-prefix отличается от префикса (prefix), когда зависящие от платформы файлы (например, исполняемые файлы и динамические библиотеки) устанавливаются в другое дерево каталогов. В типичной установке платформенно-зависимые файлы могут быть установлены в поддерево `/usr/local/plat`, а платформенно-независимые – в `/usr/local`.5253Вообще говоря, платформа – это комбинация семейств аппаратного и программного обеспечения; например, машины Sparc под управлением ОС Solaris 2.x считаются одной платформой, машины Intel под Solaris 2.x – другой, а машины Intel под Linux – третьей. Разные основные версии одной и той же ОС обычно также образуют разные платформы. Операционные системы, отличные от Unix, – это отдельная история; стратегии установки на этих системах настолько различаются, что префикс и exec-prefix не имеют смысла и устанавливаются в пустую строку. Обратите внимание: скомпилированные файлы байт-кода Python не зависят от платформы (но не от версии Python, под которой они были скомпилированы!).5455Системные администраторы знают, как настроить программы **mount** или **automount** для совместного использования `/usr/local` между платформами, при этом `/usr/local/plat` будет отдельной файловой системой для каждой платформы.5657#### `char* Py_GetProgramFullPath()`5859Возвращает полное имя программы исполняемого файла Python; оно вычисляется как побочный эффект при получении пути поиска модулей по умолчанию из имени программы (заданного с помощью [`Py_SetProgramName()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetProgramName) выше). Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение. Значение доступно коду Python как `sys.executable`.6061#### `char* Py_GetPath()`6263Возвращает путь поиска модулей по умолчанию; он вычисляется из имени программы (заданного с помощью [`Py_SetProgramName()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetProgramName) выше) и некоторых переменных окружения. Возвращаемая строка состоит из последовательности имён каталогов, разделённых символом-разделителем, зависящим от платформы. Символ-разделитель – `':'` в Unix и Mac OS X, `';'` в Windows. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Список [`sys.path`](https://python-all.ru/2.7/library/sys.html#sys.path) инициализируется этим значением при запуске интерпретатора; впоследствии его можно (и обычно так и делают) изменить, чтобы изменить путь поиска для загрузки модулей.6465#### `const char* Py_GetVersion()`6667Возвращает версию данного интерпретатора Python. Это строка, которая выглядит примерно так:6869```c70"1.5 (#67, Dec 31 1997, 22:34:28) [GCC 2.7.2.2]"71```7273Первое слово (до первого пробела) – это текущая версия Python; первые три символа – это major и minor версии, разделённые точкой. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно в коде Python как `sys.version`.7475#### `const char* Py_GetPlatform()`7677Возвращает идентификатор платформы для текущей платформы. В Unix он формируется из «официального» названия операционной системы, приведённого к нижнему регистру, за которым следует номер основной версии; например, для Solaris 2.x (также известной как SunOS 5.x) значением является `'sunos5'`. В Mac OS X это `'darwin'`. В Windows это `'win'`. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно из кода Python как `sys.platform`.7879#### `const char* Py_GetCopyright()`8081Возвращает официальную строку авторских прав для текущей версии Python, например8283`'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'`8485Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Значение доступно в коде Python как `sys.copyright`.8687#### `const char* Py_GetCompiler()`8889Возвращает указание компилятора, использованного для сборки текущей версии Python, в квадратных скобках, например:9091```c92"[GCC 2.7.2.2]"93```9495Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Значение доступно коду Python как часть переменной `sys.version`.9697#### `const char* Py_GetBuildInfo()`9899Возвращает информацию о номере сборки, дате и времени сборки текущего экземпляра интерпретатора Python, например100101```c102"#67, Aug 1 1997, 22:34:28"103```104105Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Значение доступно коду Python как часть переменной `sys.version`.106107#### `void PySys_SetArgvEx(int argc, char **argv, int updatepath)`108109Устанавливает [`sys.argv`](https://python-all.ru/2.7/library/sys.html#sys.argv) на основе *argc* и *argv*. Эти параметры похожи на передаваемые функции `main()` программы, с тем отличием, что первый элемент должен указывать на исполняемый файл сценария, а не на исполняемый файл, в котором работает интерпретатор Python. Если запускаемый сценарий отсутствует, первый элемент в *argv* может быть пустой строкой. Если этой функции не удаётся инициализировать [`sys.argv`](https://python-all.ru/2.7/library/sys.html#sys.argv), фатальная ситуация сигнализируется с помощью [`Py_FatalError()`](https://python-all.ru/2.7/c-api/sys.html#c.Py_FatalError).110111Если *updatepath* равен нулю, на этом работа функции заканчивается. Если *updatepath* не равен нулю, функция также изменяет [`sys.path`](https://python-all.ru/2.7/library/sys.html#sys.path) по следующему алгоритму:112113- Если в `argv[0]` передано имя существующего сценария, то абсолютный путь к каталогу, в котором находится сценарий, добавляется в начало [`sys.path`](https://python-all.ru/2.7/library/sys.html#sys.path).114- В противном случае (то есть если *argc* равен 0 или `argv[0]` не указывает на существующее имя файла), к [`sys.path`](https://python-all.ru/2.7/library/sys.html#sys.path) добавляется пустая строка, что эквивалентно добавлению текущего рабочего каталога (`"."`).115116> **Примечание**117>118> Рекомендуется, чтобы приложения, встраивающие интерпретатор Python для целей, отличных от выполнения одного скрипта, передавали `0` в качестве *updatepath*, и обновляли [`sys.path`](https://python-all.ru/2.7/library/sys.html#sys.path) самостоятельно, если это необходимо. См. [CVE-2008-5983](https://python-all.ru/2.7/c-api/init.html).119>120> В версиях до 2.6.6 того же эффекта можно добиться, вручную удалив первый элемент [`sys.path`](https://python-all.ru/2.7/library/sys.html#sys.path) после вызова [`PySys_SetArgv()`](https://python-all.ru/2.7/c-api/init.html#c.PySys_SetArgv), например используя:121>122> ```c123> PyRun_SimpleString("import sys; sys.path.pop(0)\n");124> ```125126Новое в версии 2.6.6.127128#### `void PySys_SetArgv(int argc, char **argv)`129130Эта функция работает как [`PySys_SetArgvEx()`](https://python-all.ru/2.7/c-api/init.html#c.PySys_SetArgvEx) с *updatepath*, установленным в `1`.131132#### `void Py_SetPythonHome(char *home)`133134Устанавливает домашний каталог по умолчанию, то есть расположение стандартных библиотек Python. См. [`PYTHONHOME`](https://python-all.ru/2.7/using/cmdline.html#envvar-PYTHONHOME) для пояснения значения строки аргумента.135136Аргумент должен указывать на строку символов, завершающуюся нулём, в статической памяти, содержимое которой не будет изменяться в течение всего времени выполнения программы. Никакой код в интерпретаторе Python не будет менять содержимое этой памяти.137138#### `char* Py_GetPythonHome()`139140Возвращает «домашний» каталог по умолчанию, то есть значение, установленное предыдущим вызовом [`Py_SetPythonHome()`](https://python-all.ru/2.7/c-api/init.html#c.Py_SetPythonHome), или значение переменной окружения [`PYTHONHOME`](https://python-all.ru/2.7/using/cmdline.html#envvar-PYTHONHOME), если она задана.141142## Состояние потока и глобальная блокировка интерпретатора143144Интерпретатор Python не является полностью потокобезопасным. Для поддержки многопоточных программ на Python существует глобальная блокировка, называемая [глобальной блокировкой интерпретатора](https://python-all.ru/2.7/glossary.html#term-global-interpreter-lock) или [GIL](https://python-all.ru/2.7/glossary.html#term-gil), которую текущий поток должен удерживать перед тем, как безопасно обращаться к объектам Python. Без этой блокировки даже простейшие операции могут вызывать проблемы в многопоточной программе: например, когда два потока одновременно увеличивают счётчик ссылок одного и того же объекта, счётчик может в итоге увеличиться только один раз вместо двух.145146Поэтому существует правило: только поток, захвативший [GIL](https://python-all.ru/2.7/glossary.html#term-gil), может работать с объектами Python или вызывать функции Python/C API. Для эмуляции параллелизма выполнения интерпретатор регулярно пытается переключать потоки (см. [`sys.setcheckinterval()`](https://python-all.ru/2.7/library/sys.html#sys.setcheckinterval)). Блокировка также освобождается вокруг потенциально блокирующих операций ввода-вывода, таких как чтение или запись файла, чтобы тем временем могли работать другие потоки Python.147148Интерпретатор Python хранит некоторую служебную информацию, специфичную для потока, в структуре данных, называемой [`PyThreadState`](https://python-all.ru/2.7/c-api/init.html#c.PyThreadState). Существует также одна глобальная переменная, указывающая на текущий [`PyThreadState`](https://python-all.ru/2.7/c-api/init.html#c.PyThreadState): её можно получить с помощью [`PyThreadState_Get()`](https://python-all.ru/2.7/c-api/init.html#c.PyThreadState_Get).149150### Освобождение GIL из кода расширения151152Большая часть кода расширения, работающего с [GIL](https://python-all.ru/2.7/glossary.html#term-gil), имеет следующую простую структуру:153154```c155Save the thread state in a local variable.156Release the global interpreter lock.157... Do some blocking I/O operation ...158Reacquire the global interpreter lock.159Restore the thread state from the local variable.160```161162Это настолько распространено, что существует пара макросов для упрощения:163164```c165Py_BEGIN_ALLOW_THREADS166... Do some blocking I/O operation ...167Py_END_ALLOW_THREADS168```169170Макрос [`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_BEGIN_ALLOW_THREADS) открывает новый блок и объявляет скрытую локальную переменную; макрос [`Py_END_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_END_ALLOW_THREADS) закрывает блок. Эти два макроса по-прежнему доступны, даже если Python скомпилирован без поддержки потоков (их подстановка просто пуста).171172Когда поддержка потоков включена, указанный выше блок раскрывается в следующий код:173174```c175PyThreadState *_save;176177_save = PyEval_SaveThread();178...Do some blocking I/O operation...179PyEval_RestoreThread(_save);180```181182Вот как работают эти функции: глобальная блокировка интерпретатора используется для защиты указателя на текущее состояние потока. При освобождении блокировки и сохранении состояния потока указатель на текущее состояние потока должен быть получен до освобождения блокировки (поскольку другой поток может немедленно захватить блокировку и сохранить своё состояние потока в глобальной переменной). И наоборот, при захвате блокировки и восстановлении состояния потока блокировка должна быть захвачена до сохранения указателя на состояние потока.183184> **Примечание**185>186> Вызов системных функций ввода-вывода – это наиболее распространённый случай освобождения GIL, но он также может быть полезен перед вызовом длительных вычислений, не требующих доступа к объектам Python, таких как функции сжатия или шифрования, работающие с буферами памяти. Например, стандартные модули [`zlib`](https://python-all.ru/2.7/library/zlib.html#module-zlib) и [`hashlib`](https://python-all.ru/2.7/library/hashlib.html#module-hashlib) освобождают GIL при сжатии или хешировании данных.187188### Потоки, созданные не из Python189190Когда потоки создаются с помощью специализированных Python API (например, модуля [`threading`](https://python-all.ru/2.7/library/threading.html#module-threading)), с ними автоматически связывается состояние потока, и приведённый выше код корректен. Однако, когда потоки создаются из C (например, сторонней библиотекой с собственным управлением потоками), они не удерживают GIL и для них не существует структуры состояния потока.191192Если необходимо вызвать код Python из этих потоков (часто это будет частью API колбэков, предоставляемого упомянутой сторонней библиотекой), сначала нужно зарегистрировать эти потоки в интерпретаторе, создав структуру данных состояния потока, затем захватить GIL и, наконец, сохранить указатель на их состояние потока, прежде чем можно будет начать использовать Python/C API. После завершения следует сбросить указатель состояния потока, освободить GIL и освободить структуру данных состояния потока.193194Функции [`PyGILState_Ensure()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Ensure) и [`PyGILState_Release()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Release) делают всё вышеописанное автоматически. Типичный способ вызова Python из потока C:195196```c197PyGILState_STATE gstate;198gstate = PyGILState_Ensure();199200/* Выполнить действия Python здесь. */201result = CallSomeFunction();202/* вычислить результат или обработать исключение */203204/* Освободить поток. После этой точки API Python не допускается. */205PyGILState_Release(gstate);206```207208Обратите внимание, что функции `PyGILState_*()` предполагают наличие только одного глобального интерпретатора (создаваемого автоматически с помощью [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize)). Python поддерживает создание дополнительных интерпретаторов (с помощью [`Py_NewInterpreter()`](https://python-all.ru/2.7/c-api/init.html#c.Py_NewInterpreter)), но смешивание нескольких интерпретаторов и API `PyGILState_*()` не поддерживается.209210Ещё одна важная особенность поведения потоков – их реакция на вызов C `fork()`. В большинстве систем с `fork()` после порождения процесса (fork) остаётся существовать только тот поток, который вызвал fork. Это также означает, что любые блокировки, удерживаемые другими потоками, никогда не будут освобождены. Python решает эту проблему для [`os.fork()`](https://python-all.ru/2.7/library/os.html#os.fork), захватывая блокировки, которые он использует внутренне, перед fork и освобождая их после. Кроме того, он сбрасывает любые [объекты Lock](https://python-all.ru/2.7/library/threading.html#lock-objects) в дочернем процессе. При расширении или встраивании Python нет способа уведомить Python о дополнительных (не-Python) блокировках, которые необходимо захватить до fork или сбросить после. Для достижения того же эффекта потребуются средства ОС, такие как `pthread_atfork()`. Кроме того, при расширении или встраивании Python вызов `fork()` напрямую, а не через [`os.fork()`](https://python-all.ru/2.7/library/os.html#os.fork) (и возврат в Python или вызов Python) может привести к взаимоблокировке, если одна из внутренних блокировок Python удерживается потоком, который перестал существовать после fork. [`PyOS_AfterFork()`](https://python-all.ru/2.7/c-api/sys.html#c.PyOS_AfterFork) пытается сбросить необходимые блокировки, но не всегда может это сделать.211212### API высокого уровня213214Это наиболее часто используемые типы и функции при написании кода C-расширения или при встраивании интерпретатора Python:215216**`PyInterpreterState`**217218Эта структура данных представляет состояние, совместно используемое несколькими взаимодействующими потоками. Потоки, принадлежащие одному интерпретатору, разделяют администрирование модулей и несколько других внутренних элементов. В этой структуре нет открытых членов.219220Потоки, принадлежащие разным интерпретаторам, изначально не разделяют ничего, кроме состояния процесса, такого как доступная память, открытые файловые дескрипторы и т.п. Глобальная блокировка интерпретатора также разделяется всеми потоками, независимо от того, какому интерпретатору они принадлежат.221222**`PyThreadState`**223224Эта структура данных представляет состояние одного потока. Единственный открытый член данных – [`PyInterpreterState *`](https://python-all.ru/2.7/c-api/init.html#c.PyInterpreterState)`interp`, который указывает на состояние интерпретатора этого потока.225226#### `void PyEval_InitThreads()`227228Инициализирует и захватывает глобальную блокировку интерпретатора. Её следует вызывать в главном потоке перед созданием второго потока или выполнением любых других операций с потоками, таких как [`PyEval_ReleaseLock()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_ReleaseLock) или `PyEval_ReleaseThread(tstate)`. Её не нужно вызывать перед вызовом [`PyEval_SaveThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_SaveThread) или [`PyEval_RestoreThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_RestoreThread).229230При повторном вызове эта функция ничего не делает. Её можно безопасно вызывать до вызова [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize).231232> **Примечание**233>234> Когда существует только главный поток, операции GIL не требуются. Это обычная ситуация (большинство программ Python не используют потоки), и операции блокировки немного замедляют интерпретатор. Поэтому блокировка изначально не создаётся. Эта ситуация эквивалентна уже захваченной блокировке: когда есть только один поток, все операции с объектами безопасны. Следовательно, когда эта функция инициализирует глобальную блокировку интерпретатора, она также захватывает её. Перед тем как модуль `_thread` Python создаёт новый поток, зная, что блокировка либо уже захвачена, либо ещё не создана, он вызывает [`PyEval_InitThreads()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_InitThreads). Когда этот вызов возвращается, гарантируется, что блокировка создана и вызвавший поток захватил её.235>236> **Не**безопасно вызывать эту функцию, когда неизвестно, какой поток (если таковой есть) в данный момент удерживает глобальную блокировку интерпретатора.237>238> Эта функция недоступна, если поддержка потоков отключена на этапе компиляции.239240#### `int PyEval_ThreadsInitialized()`241242Возвращает ненулевое значение, если [`PyEval_InitThreads()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_InitThreads) была вызвана. Эту функцию можно вызывать без удержания GIL, и поэтому её можно использовать, чтобы избежать вызовов API блокировки при работе в однопоточном режиме. Эта функция недоступна, если поддержка потоков отключена на этапе компиляции.243244Новое в версии 2.4.245246#### `PyThreadState* PyEval_SaveThread()`247248Освобождает глобальную блокировку интерпретатора (если она создана и поддержка потоков включена) и сбрасывает состояние потока в *NULL*, возвращая предыдущее состояние потока (которое не равно *NULL*). Если блокировка была создана, текущий поток должен был захватить её. (Эта функция доступна, даже если поддержка потоков отключена на этапе компиляции.)249250#### `void PyEval_RestoreThread(PyThreadState *tstate)`251252Захватывает глобальную блокировку интерпретатора (если она создана и поддержка потоков включена) и устанавливает состояние потока в *tstate*, который не должен быть *NULL*. Если блокировка была создана, текущий поток не должен был захватить её, иначе возникнет взаимоблокировка. (Эта функция доступна, даже если поддержка потоков отключена на этапе компиляции.)253254#### `PyThreadState* PyThreadState_Get()`255256Возвращает текущее состояние потока. Должна быть захвачена глобальная блокировка интерпретатора. Если текущее состояние потока равно *NULL*, возникает фатальная ошибка (таким образом, вызывающему коду не нужно проверять на *NULL*).257258#### `PyThreadState* PyThreadState_Swap(PyThreadState *tstate)`259260Заменяет текущее состояние потока на состояние, заданное аргументом *tstate*, который может быть *NULL*. Глобальная блокировка интерпретатора должна быть захвачена и не освобождается.261262#### `void PyEval_ReInitThreads()`263264Эта функция вызывается из [`PyOS_AfterFork()`](https://python-all.ru/2.7/c-api/sys.html#c.PyOS_AfterFork), чтобы гарантировать, что вновь созданные дочерние процессы не удерживают блокировки, относящиеся к потокам, которые не выполняются в дочернем процессе.265266Следующие функции используют локальное хранилище потока и несовместимы с подынтерпретаторами:267268#### `PyGILState_STATE PyGILState_Ensure()`269270Обеспечивает, что текущий поток готов к вызову Python C API независимо от текущего состояния Python или глобальной блокировки интерпретатора. Этот вызов может вызываться потоком сколько угодно раз, при условии, что каждый вызов завершается вызовом [`PyGILState_Release()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Release). В общем случае другие API, связанные с потоками, могут использоваться между вызовами [`PyGILState_Ensure()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Ensure) и [`PyGILState_Release()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Release), если состояние потока будет восстановлено в предыдущее состояние перед Release(). Например, обычное использование макросов [`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_BEGIN_ALLOW_THREADS) и [`Py_END_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_END_ALLOW_THREADS) допустимо.271272Возвращаемое значение – это непрозрачный «дескриптор» состояния потока на момент вызова [`PyGILState_Ensure()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Ensure), и его необходимо передать в [`PyGILState_Release()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Release), чтобы гарантировать, что Python останется в том же состоянии. Хотя рекурсивные вызовы разрешены, эти дескрипторы *нельзя* совместно использовать – каждый уникальный вызов [`PyGILState_Ensure()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Ensure) должен сохранить свой дескриптор для вызова [`PyGILState_Release()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Release).273274Когда функция возвращает управление, текущий поток будет удерживать GIL и сможет вызывать произвольный код Python. Сбой является фатальной ошибкой.275276Новое в версии 2.3.277278#### `void PyGILState_Release(PyGILState_STATE)`279280Освобождает любые ресурсы, полученные ранее. После этого вызова состояние Python будет таким же, как до соответствующего вызова [`PyGILState_Ensure()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Ensure) (но обычно это состояние неизвестно вызывающему, поэтому используется GILState API).281282Каждый вызов [`PyGILState_Ensure()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Ensure) должен сопровождаться вызовом [`PyGILState_Release()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Release) в том же потоке.283284Новое в версии 2.3.285286#### `PyThreadState* PyGILState_GetThisThreadState()`287288Возвращает состояние текущего потока. Может вернуть `NULL`, если на текущем потоке не использовался GILState API. Обратите внимание, что главный поток всегда имеет такое состояние, даже если для него не вызывался auto-thread-state. Это вспомогательная/диагностическая функция.289290Новое в версии 2.3.291292Следующие макросы обычно используются без точки с запятой в конце; примеры использования можно найти в дистрибутиве исходного кода Python.293294**`Py_BEGIN_ALLOW_THREADS`**295296Этот макрос разворачивается в `{ PyThreadState *_save; _save = PyEval_SaveThread();`. Обратите внимание, что он содержит открывающую фигурную скобку; он должен сочетаться с последующим макросом [`Py_END_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_END_ALLOW_THREADS). См. выше для дальнейшего обсуждения этого макроса. Он ничего не делает, если поддержка потоков отключена во время компиляции.297298**`Py_END_ALLOW_THREADS`**299300Этот макрос разворачивается в `PyEval_RestoreThread(_save); }`. Обратите внимание, что он содержит закрывающую фигурную скобку; он должен сочетаться с предыдущим макросом [`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_BEGIN_ALLOW_THREADS). См. выше для дальнейшего обсуждения этого макроса. Он ничего не делает, если поддержка потоков отключена во время компиляции.301302**`Py_BLOCK_THREADS`**303304Этот макрос разворачивается в `PyEval_RestoreThread(_save);`: он эквивалентен [`Py_END_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_END_ALLOW_THREADS) без закрывающей скобки. Он ничего не делает, если поддержка потоков отключена во время компиляции.305306**`Py_UNBLOCK_THREADS`**307308Этот макрос разворачивается в `_save = PyEval_SaveThread();`: он эквивалентен [`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.7/c-api/init.html#c.Py_BEGIN_ALLOW_THREADS) без открывающей скобки и объявления переменной. Он ничего не делает, если поддержка потоков отключена во время компиляции.309310### Низкоуровневый API311312Все следующие функции доступны только при включенной поддержке потоков во время компиляции и должны вызываться только после создания глобальной блокировки интерпретатора.313314#### `PyInterpreterState* PyInterpreterState_New()`315316Создаёт новый объект состояния интерпретатора. Глобальная блокировка интерпретатора может не удерживаться, но может удерживаться, если необходимо сериализовать вызовы этой функции.317318#### `void PyInterpreterState_Clear(PyInterpreterState *interp)`319320Сбрасывает всю информацию в объекте состояния интерпретатора. Глобальная блокировка интерпретатора должна удерживаться.321322#### `void PyInterpreterState_Delete(PyInterpreterState *interp)`323324Уничтожает объект состояния интерпретатора. Глобальная блокировка интерпретатора может не удерживаться. Состояние интерпретатора должно быть предварительно сброшено вызовом [`PyInterpreterState_Clear()`](https://python-all.ru/2.7/c-api/init.html#c.PyInterpreterState_Clear).325326#### `PyThreadState* PyThreadState_New(PyInterpreterState *interp)`327328Создаёт новый объект состояния потока, принадлежащий данному объекту интерпретатора. Глобальная блокировка интерпретатора может не удерживаться, но может удерживаться, если необходимо сериализовать вызовы этой функции.329330#### `void PyThreadState_Clear(PyThreadState *tstate)`331332Сбрасывает всю информацию в объекте состояния потока. Глобальная блокировка интерпретатора должна удерживаться.333334#### `void PyThreadState_Delete(PyThreadState *tstate)`335336Уничтожает объект состояния потока. Глобальная блокировка интерпретатора может не удерживаться. Состояние потока должно быть предварительно сброшено вызовом [`PyThreadState_Clear()`](https://python-all.ru/2.7/c-api/init.html#c.PyThreadState_Clear).337338#### `PyObject* PyThreadState_GetDict()`339340*Возвращаемое значение: заимствованная ссылка.*341342Возвращает словарь, в котором расширения могут хранить информацию о состоянии, специфичном для потока. Каждое расширение должно использовать уникальный ключ для хранения состояния в словаре. Эту функцию можно вызывать, даже если текущее состояние потока недоступно. Если эта функция возвращает *NULL*, исключение не было возбуждено, и вызывающий код должен считать, что текущее состояние потока недоступно.343344Изменено в версии 2.3: Ранее это можно было вызывать только при активном текущем потоке, и *NULL* означал, что было возбуждено исключение.345346#### `int PyThreadState_SetAsyncExc(long id, PyObject *exc)`347348Асинхронно возбуждает исключение в потоке. Аргумент *id* – это идентификатор потока целевого потока; *exc* – это объект исключения, которое нужно возбудить. Эта функция не крадёт ссылки на *exc*. Для предотвращения наивного misuse требуется написать собственное C-расширение для её вызова. Должна вызываться с удержанием GIL. Возвращает количество изменённых состояний потока; обычно это единица, но будет нулём, если идентификатор потока не найден. Если *exc* равно `NULL`, отложенное исключение (если есть) для потока очищается. Эта функция не возбуждает исключений.349350Новое в версии 2.3.351352#### `void PyEval_AcquireThread(PyThreadState *tstate)`353354Захватывает глобальную блокировку интерпретатора и устанавливает текущее состояние потока в *tstate*, который не должен быть *NULL*. Блокировка должна быть создана ранее. Если этот поток уже удерживает блокировку, возникает взаимоблокировка.355356[`PyEval_RestoreThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_RestoreThread) – это функция более высокого уровня, которая всегда доступна (даже если поддержка потоков не включена или потоки не были инициализированы).357358#### `void PyEval_ReleaseThread(PyThreadState *tstate)`359360Сбрасывает текущее состояние потока в *NULL* и освобождает глобальную блокировку интерпретатора. Блокировка должна быть создана ранее и должна удерживаться текущим потоком. Аргумент *tstate*, который не должен быть *NULL*, используется только для проверки того, что он представляет текущее состояние потока – если это не так, сообщается о фатальной ошибке.361362[`PyEval_SaveThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_SaveThread) – это функция более высокого уровня, которая всегда доступна (даже если поддержка потоков не включена или потоки не были инициализированы).363364#### `void PyEval_AcquireLock()`365366Захватывает глобальную блокировку интерпретатора. Блокировка должна быть создана заранее. Если этот поток уже удерживает блокировку, возникает взаимоблокировка.367368> **Предупреждение**369>370> Эта функция не изменяет состояние текущего потока. Пожалуйста, используйте [`PyEval_RestoreThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_RestoreThread) или [`PyEval_AcquireThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_AcquireThread) вместо этого.371372#### `void PyEval_ReleaseLock()`373374Освобождает глобальную блокировку интерпретатора. Блокировка должна быть создана заранее.375376> **Предупреждение**377>378> Эта функция не изменяет состояние текущего потока. Пожалуйста, используйте [`PyEval_SaveThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_SaveThread) или [`PyEval_ReleaseThread()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_ReleaseThread) вместо этого.379380## Поддержка под-интерпретаторов381382Хотя в большинстве случаев встраивается только один интерпретатор Python, бывают ситуации, когда необходимо создать несколько независимых интерпретаторов в одном процессе и даже в одном потоке. Под-интерпретаторы позволяют это сделать. Переключаться между под-интерпретаторами можно с помощью функции [`PyThreadState_Swap()`](https://python-all.ru/2.7/c-api/init.html#c.PyThreadState_Swap). Для создания и уничтожения под-интерпретаторов используются следующие функции:383384#### `PyThreadState* Py_NewInterpreter()`385386Создаёт новый под-интерпретатор. Это (почти) полностью независимое окружение для выполнения кода Python. В частности, новый интерпретатор имеет отдельные, независимые версии всех импортированных модулей, включая фундаментальные модули `builtins`, [`__main__`](https://python-all.ru/2.7/library/__main__.html#module-__main__) и [`sys`](https://python-all.ru/2.7/library/sys.html#module-sys). Таблица загруженных модулей (`sys.modules`) и путь поиска модулей (`sys.path`) также отдельные. В новом окружении нет переменной `sys.argv` . У него есть новые файловые объекты стандартных потоков ввода-вывода `sys.stdin`, `sys.stdout` и `sys.stderr` (однако они ссылаются на те же нижележащие файловые дескрипторы).387388Возвращаемое значение указывает на первое состояние потока, созданное в новом под-интерпретаторе. Это состояние потока создаётся в текущем состоянии потока. Обратите внимание, что фактический поток не создаётся; см. обсуждение состояний потока ниже. Если создание нового интерпретатора не удалось, возвращается *NULL*; исключение не устанавливается, поскольку состояние исключения хранится в текущем состоянии потока, и текущего состояния потока может не быть. (Как и все другие функции Python/C API, глобальная блокировка интерпретатора должна быть захвачена перед вызовом этой функции и остаётся захваченной при возврате; однако, в отличие от большинства других функций Python/C API, при входе необязательно наличие текущего состояния потока.)389390Модули расширений разделяются между (под-)интерпретаторами следующим образом: при первом импорте конкретного расширения оно инициализируется обычным образом, а (поверхностная) копия словаря его модуля сохраняется. Когда то же расширение импортируется другим (под-)интерпретатором, инициализируется новый модуль и заполняется содержимым этой копии; функция `init` расширения не вызывается. Обратите внимание, что это отличается от ситуации, когда расширение импортируется после полной переинициализации интерпретатора вызовами функций [`Py_Finalize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Finalize) и [`Py_Initialize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Initialize); в этом случае функция `initmodule` расширения *вызывается* снова.391392#### `void Py_EndInterpreter(PyThreadState *tstate)`393394Уничтожает (под-)интерпретатор, представленный заданным состоянием потока. Указанное состояние потока должно быть текущим состоянием потока. См. обсуждение состояний потока ниже. Когда вызов возвращается, текущее состояние потока равно *NULL*. Все состояния потока, связанные с этим интерпретатором, уничтожаются. (Глобальная блокировка интерпретатора должна быть захвачена перед вызовом этой функции и остаётся захваченной при возврате.) [`Py_Finalize()`](https://python-all.ru/2.7/c-api/init.html#c.Py_Finalize) уничтожит все под-интерпретаторы, которые не были явно уничтожены к этому моменту.395396### Ошибки и предостережения397398Поскольку под-интерпретаторы (и основной интерпретатор) являются частью одного процесса, изоляция между ними не идеальна: например, используя низкоуровневые файловые операции, такие как [`os.close()`](https://python-all.ru/2.7/library/os.html#os.close), они могут (случайно или злонамеренно) влиять на открытые файлы друг друга. Из-за способа разделения расширений между (под-)интерпретаторами некоторые расширения могут работать неправильно; это особенно вероятно, если расширение использует (статические) глобальные переменные или манипулирует словарем своего модуля после инициализации. Можно вставлять объекты, созданные в одном под-интерпретаторе, в пространство имен другого под-интерпретатора; это следует делать с большой осторожностью, чтобы избежать совместного использования определенных пользователем функций, методов, экземпляров или классов между под-интерпретаторами, так как операции импорта, выполняемые такими объектами, могут повлиять на словарь загруженных модулей не того (под-)интерпретатора.399400Также обратите внимание, что комбинирование этой функциональности с API `PyGILState_*()` является деликатным, поскольку эти API предполагают взаимно однозначное соответствие между состояниями потоков Python и потоками уровня ОС, а это предположение нарушается наличием под-интерпретаторов. Настоятельно рекомендуется не переключать под-интерпретаторы между парой соответствующих вызовов [`PyGILState_Ensure()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Ensure) и [`PyGILState_Release()`](https://python-all.ru/2.7/c-api/init.html#c.PyGILState_Release). Более того, расширения (такие как [`ctypes`](https://python-all.ru/2.7/library/ctypes.html#module-ctypes)), использующие эти API для вызова кода Python из потоков, созданных не в Python, вероятно, будут работать неправильно при использовании под-интерпретаторов.401402## Асинхронные уведомления403404Предоставляется механизм для асинхронных уведомлений основному потоку интерпретатора. Эти уведомления имеют форму указателя на функцию и аргумента в виде указателя void.405406#### `int Py_AddPendingCall(int (*func)(void *), void *arg)`407408Планирует вызов функции из основного потока интерпретатора. В случае успеха возвращается `0`, и *func* помещается в очередь для вызова в основном потоке. В случае неудачи возвращается `-1` без установки какого-либо исключения.409410При успешной постановке в очередь *func* будет *в конечном итоге* вызвана из основного потока интерпретатора с аргументом *arg*. Она будет вызвана асинхронно по отношению к нормально выполняющемуся коду Python, но при соблюдении обоих этих условий:411412- на границе [байткода](https://python-all.ru/2.7/glossary.html#term-bytecode);413- при этом главный поток удерживает [глобальную блокировку интерпретатора](https://python-all.ru/2.7/glossary.html#term-global-interpreter-lock) (поэтому *func* может использовать полный C API).414415*func* должна возвращать `0` при успехе или `-1` при неудаче с установленным исключением. *func* не будет прервана для рекурсивного выполнения другого асинхронного уведомления, но её всё ещё можно прервать для переключения потоков, если глобальная блокировка интерпретатора освобождена.416417Для выполнения этой функции не требуется текущее состояние потока, и ей не нужна глобальная блокировка интерпретатора.418419> **Предупреждение**420>421> Это низкоуровневая функция, полезная только в особых случаях. Нет гарантии, что *func* будет вызвана максимально быстро. Если главный поток занят выполнением системного вызова, *func* не будет вызвана до возврата из системного вызова. Эта функция в целом **не** подходит для вызова кода Python из произвольных C-потоков. Вместо неё используйте [PyGILState API](https://python-all.ru/2.7/c-api/init.html#gilstate).422423Новое в версии 2.7.424425## Профилирование и трассировка426427Интерпретатор Python предоставляет низкоуровневую поддержку для подключения средств профилирования и трассировки выполнения. Они используются в инструментах профилирования, отладки и анализа покрытия.428429Начиная с Python 2.2, реализация этого механизма была существенно переработана, и был добавлен интерфейс на C. Этот интерфейс на C позволяет коду профилирования или трассировки избежать накладных расходов на вызов через вызываемые объекты уровня Python, выполняя вместо этого прямой вызов функции на C. Основные атрибуты механизма не изменились; интерфейс позволяет устанавливать функции трассировки для каждого потока, и базовые события, сообщаемые функции трассировки, остались теми же, что сообщались функциям трассировки уровня Python в предыдущих версиях.430431**int `(*Py_tracefunc)`([PyObject](https://python-all.ru/2.7/c-api/structures.html#c.PyObject) *\*obj*, PyFrameObject *\*frame*, int *what*, [PyObject](https://python-all.ru/2.7/c-api/structures.html#c.PyObject) *\*arg*)**432433Тип функции трассировки, зарегистрированной с помощью [`PyEval_SetProfile()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_SetProfile) и [`PyEval_SetTrace()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_SetTrace). Первый параметр – это объект, переданный функции регистрации как *obj*, *frame* – это объект фрейма, к которому относится событие, *what* – одна из констант `PyTrace_CALL`, `PyTrace_EXCEPTION`, `PyTrace_LINE`, `PyTrace_RETURN`, `PyTrace_C_CALL`, `PyTrace_C_EXCEPTION` или `PyTrace_C_RETURN`, а *arg* зависит от значения *what*:434435| Значение *what* | Смысл *arg* |436| --- | --- |437| `PyTrace_CALL` | Всегда [`Py_None`](https://python-all.ru/2.7/c-api/none.html#c.Py_None). |438| `PyTrace_EXCEPTION` | Информация об исключении, возвращаемая [`sys.exc_info()`](https://python-all.ru/2.7/library/sys.html#sys.exc_info). |439| `PyTrace_LINE` | Всегда [`Py_None`](https://python-all.ru/2.7/c-api/none.html#c.Py_None). |440| `PyTrace_RETURN` | Значение, возвращаемое вызывающему коду, или *NULL*, если вызвано исключением. |441| `PyTrace_C_CALL` | Вызываемый объект функции. |442| `PyTrace_C_EXCEPTION` | Вызываемый объект функции. |443| `PyTrace_C_RETURN` | Вызываемый объект функции. |444445**int `PyTrace_CALL`**446447Значение параметра *what* для функции [`Py_tracefunc`](https://python-all.ru/2.7/c-api/init.html#c.Py_tracefunc), когда сообщается о новом вызове функции или метода, или о новом входе в генератор. Обратите внимание, что создание итератора для функции-генератора не сообщается, поскольку в соответствующем фрейме не происходит передачи управления байт-коду Python.448449**int `PyTrace_EXCEPTION`**450451Значение параметра *what* в функции [`Py_tracefunc`](https://python-all.ru/2.7/c-api/init.html#c.Py_tracefunc), когда возникло исключение. Функция колбэка вызывается с этим значением для *what* после обработки любого байт-кода, после которого исключение оказывается установленным в выполняемом фрейме. Эффект этого заключается в том, что по мере распространения исключения, вызывающего раскрутку стека Python, колбэк вызывается при возврате в каждый фрейм по мере распространения исключения. Только функции трассировки получают эти события; профилировщику они не нужны.452453**int `PyTrace_LINE`**454455Значение, передаваемое в качестве параметра *what* в трассировочную функцию (но не в профилирующую функцию), когда сообщается о событии номера строки.456457**int `PyTrace_RETURN`**458459Значение параметра *what* для функций [`Py_tracefunc`](https://python-all.ru/2.7/c-api/init.html#c.Py_tracefunc), когда вызов собирается вернуться.460461**int `PyTrace_C_CALL`**462463Значение параметра *what* для функций [`Py_tracefunc`](https://python-all.ru/2.7/c-api/init.html#c.Py_tracefunc), когда собирается быть вызвана C-функция.464465**int `PyTrace_C_EXCEPTION`**466467Значение параметра *what* для функций [`Py_tracefunc`](https://python-all.ru/2.7/c-api/init.html#c.Py_tracefunc), когда C-функция вызвала исключение.468469**int `PyTrace_C_RETURN`**470471Значение параметра *what* для функций [`Py_tracefunc`](https://python-all.ru/2.7/c-api/init.html#c.Py_tracefunc), когда C-функция вернулась.472473#### `void PyEval_SetProfile(Py_tracefunc func, PyObject *obj)`474475Устанавливает профилирующую функцию в *func*. Параметр *obj* передаётся функции в качестве первого параметра и может быть любым объектом Python или *NULL*. Если профилирующей функции необходимо сохранять состояние, использование разных значений *obj* для каждого потока предоставляет удобное и потокобезопасное место для его хранения. Профилирующая функция вызывается для всех отслеживаемых событий, кроме `PyTrace_LINE` и `PyTrace_EXCEPTION`.476477#### `void PyEval_SetTrace(Py_tracefunc func, PyObject *obj)`478479Устанавливает трассировочную функцию в *func*. Это похоже на [`PyEval_SetProfile()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_SetProfile), за исключением того, что трассировочная функция получает события номера строки и не получает никаких событий, связанных с вызовом C-функций. Любая трассировочная функция, зарегистрированная через [`PyEval_SetTrace()`](https://python-all.ru/2.7/c-api/init.html#c.PyEval_SetTrace), не будет получать `PyTrace_C_CALL`, `PyTrace_C_EXCEPTION` или `PyTrace_C_RETURN` в качестве значения параметра *what*.480481#### `PyObject* PyEval_GetCallStats(PyObject *self)`482483Возвращает кортеж счётчиков вызовов функций. Для позиций в кортеже определены константы:484485| Имя | Значение |486| --- | --- |487| `PCALL_ALL` | 0 |488| `PCALL_FUNCTION` | 1 |489| `PCALL_FAST_FUNCTION` | 2 |490| `PCALL_FASTER_FUNCTION` | 3 |491| `PCALL_METHOD` | 4 |492| `PCALL_BOUND_METHOD` | 5 |493| `PCALL_CFUNCTION` | 6 |494| `PCALL_TYPE` | 7 |495| `PCALL_GENERATOR` | 8 |496| `PCALL_OTHER` | 9 |497| `PCALL_POP` | 10 |498499`PCALL_FAST_FUNCTION` означает, что создавать кортеж аргументов не требуется. `PCALL_FASTER_FUNCTION` означает, что используется код быстрой настройки фрейма.500501Если есть вызов метода, который можно оптимизировать, изменив кортеж аргументов и вызвав функцию напрямую, он записывается дважды.502503Эта функция присутствует только если Python скомпилирован с определённым `CALL_PROFILE`.504505## Поддержка расширенного отладчика506507Эти функции предназначены только для использования расширенными инструментами отладки.508509#### `PyInterpreterState* PyInterpreterState_Head()`510511Возвращает объект состояния интерпретатора, находящийся в начале списка всех таких объектов.512513Новое в версии 2.2.514515#### `PyInterpreterState* PyInterpreterState_Next(PyInterpreterState *interp)`516517Возвращает следующий объект состояния интерпретатора после *interp* из списка всех таких объектов.518519Новое в версии 2.2.520521#### `PyThreadState * PyInterpreterState_ThreadHead(PyInterpreterState *interp)`522523Возвращает указатель на первый объект [`PyThreadState`](https://python-all.ru/2.7/c-api/init.html#c.PyThreadState) в списке потоков, связанных с интерпретатором *interp*.524525Новое в версии 2.2.526527#### `PyThreadState* PyThreadState_Next(PyThreadState *tstate)`528529Возвращает следующий объект состояния потока после *tstate* из списка всех таких объектов, принадлежащих тому же объекту [`PyInterpreterState`](https://python-all.ru/2.7/c-api/init.html#c.PyInterpreterState).530531Новое в версии 2.2.532