init.md
1> **Источник:** https://python-all.ru/2.6/c-api/init.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Инициализация, финализация и потоки89**void `Py_Initialize`()**1011Инициализирует интерпретатор Python. В приложении, встраивающем Python, эту функцию следует вызывать перед использованием любых других функций Python/C API; за исключением [`Py_SetProgramName()`](https://python-all.ru/2.6/c-api/init.html#Py_SetProgramName), [`PyEval_InitThreads()`](https://python-all.ru/2.6/c-api/init.html#PyEval_InitThreads), [`PyEval_ReleaseLock()`](https://python-all.ru/2.6/c-api/init.html#PyEval_ReleaseLock) и [`PyEval_AcquireLock()`](https://python-all.ru/2.6/c-api/init.html#PyEval_AcquireLock). Эта функция инициализирует таблицу загруженных модулей (`sys.modules`) и создаёт фундаментальные модули [`__builtin__`](https://python-all.ru/2.6/library/__builtin__.html#module-__builtin__), [`__main__`](https://python-all.ru/2.6/library/__main__.html#module-__main__) и [`sys`](https://python-all.ru/2.6/library/sys.html#module-sys). Она также инициализирует путь поиска модулей (`sys.path`). Она не устанавливает `sys.argv`; для этого используйте [`PySys_SetArgvEx()`](https://python-all.ru/2.6/c-api/init.html#PySys_SetArgvEx). При повторном вызове (без предварительного вызова [`Py_Finalize()`](https://python-all.ru/2.6/c-api/init.html#Py_Finalize)) эта функция ничего не делает. Возвращаемого значения нет; при неудачной инициализации возникает фатальная ошибка.1213**void `Py_InitializeEx`(int *initsigs*)**1415Эта функция работает как [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize), если *initsigs* равно 1. Если *initsigs* равно 0, она пропускает инициализацию регистрации обработчиков сигналов, что может быть полезно при встраивании Python.1617Новое в версии 2.4.1819**int `Py_IsInitialized`()**2021Возвращает true (ненулевое значение), если интерпретатор Python был инициализирован, и false (ноль) в противном случае. После вызова2223[`Py_Finalize()`](https://python-all.ru/2.6/c-api/init.html#Py_Finalize)2425возвращает false до тех пор, пока снова не будет вызвана2627[`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize)2829.3031**void `Py_Finalize`()**3233Отменяет всю инициализацию, выполненную [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize) и последующее использование функций Python/C API, и уничтожает все под-интерпретаторы (см. [`Py_NewInterpreter()`](https://python-all.ru/2.6/c-api/init.html#Py_NewInterpreter) ниже), которые были созданы и ещё не уничтожены после последнего вызова [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize). В идеале освобождает всю память, выделенную интерпретатором Python. Повторный вызов (без предварительного повторного вызова [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize)) ничего не делает. Возвращаемого значения нет; ошибки при финализации игнорируются.3435Эта функция предусмотрена по ряду причин. Встраивающее приложение может захотеть перезапустить Python без перезапуска самого приложения. Приложение, загрузившее интерпретатор Python из динамически загружаемой библиотеки (или DLL), может захотеть освободить всю память, выделенную Python, перед выгрузкой DLL. В процессе поиска утечек памяти в приложении разработчик может захотеть освободить всю память, выделенную Python, перед выходом из приложения.3637**Ошибки и предостережения:** Уничтожение модулей и объектов в модулях происходит в случайном порядке; это может привести к сбоям деструкторов (методов [`__del__()`](https://python-all.ru/2.6/reference/datamodel.html#object.__del__)), если они зависят от других объектов (даже функций) или модулей. Динамически загружаемые модули расширений, загруженные Python, не выгружаются. Небольшие объёмы памяти, выделенные интерпретатором Python, могут не освобождаться (если вы обнаружите утечку, сообщите о ней). Память, связанная циклическими ссылками между объектами, не освобождается. Некоторый объём памяти, выделенный модулями расширений, может не освободиться. Некоторые расширения могут работать неправильно, если их процедура инициализации вызывается более одного раза; это может произойти, если приложение вызывает [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize) и [`Py_Finalize()`](https://python-all.ru/2.6/c-api/init.html#Py_Finalize) более одного раза.3839**[PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState)\* `Py_NewInterpreter`()**4041Создаёт новый под-интерпретатор. Это (почти) полностью изолированная среда для выполнения кода Python. В частности, новый интерпретатор имеет отдельные, независимые версии всех импортированных модулей, включая фундаментальные модули [`__builtin__`](https://python-all.ru/2.6/library/__builtin__.html#module-__builtin__), [`__main__`](https://python-all.ru/2.6/library/__main__.html#module-__main__) и [`sys`](https://python-all.ru/2.6/library/sys.html#module-sys). Таблица загруженных модулей (`sys.modules`) и путь поиска модулей (`sys.path`) также разделены. В новой среде нет переменной `sys.argv`. Она имеет новые файловые объекты стандартных потоков ввода-вывода `sys.stdin`, `sys.stdout` и `sys.stderr` (однако они ссылаются на те же базовые структуры `FILE` в библиотеке C).4243Возвращаемое значение указывает на первое состояние потока, созданное в новом под-интерпретаторе. Это состояние потока создаётся в текущем состоянии потока. Обратите внимание, что фактический поток не создаётся; см. обсуждение состояний потока ниже. Если создание нового интерпретатора не удалось, возвращается *NULL*; исключение не устанавливается, поскольку состояние исключения хранится в текущем состоянии потока, и текущего состояния потока может не быть. (Как и все другие функции Python/C API, глобальная блокировка интерпретатора должна быть захвачена перед вызовом этой функции и остаётся захваченной при возврате; однако, в отличие от большинства других функций Python/C API, при входе необязательно наличие текущего состояния потока.)4445Модули расширения разделяются между (суб-)интерпретаторами следующим образом: при первом импорте конкретного расширения оно инициализируется обычным образом, и (поверхностная) копия словаря его модуля сохраняется. Когда то же расширение импортируется другим (суб-)интерпретатором, инициализируется новый модуль и заполняется содержимым этой копии; функция `init` расширения не вызывается. Обратите внимание, что это отличается от того, что происходит, когда расширение импортируется после полной переинициализации интерпретатора вызовами [`Py_Finalize()`](https://python-all.ru/2.6/c-api/init.html#Py_Finalize) и [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize); в этом случае функция `initmodule` расширения *вызывается* снова.4647**Ошибки и предостережения:** Поскольку под-интерпретаторы (и главный интерпретатор) являются частью одного процесса, изоляция между ними не идеальна – например, используя низкоуровневые файловые операции, такие как [`os.close()`](https://python-all.ru/2.6/library/os.html#os.close), они могут (случайно или злонамеренно) влиять на открытые файлы друг друга. Из-за того, как расширения разделяются между (под-)интерпретаторами, некоторые расширения могут работать некорректно; это особенно вероятно, когда расширение использует (статические) глобальные переменные или когда расширение изменяет словарь своего модуля после инициализации. Можно вставлять объекты, созданные в одном под-интерпретаторе, в пространство имён другого под-интерпретатора; это следует делать с большой осторожностью, чтобы избежать совместного использования пользовательских функций, методов, экземпляров или классов между под-интерпретаторами, поскольку операции импорта, выполняемые такими объектами, могут повлиять на словарь загруженных модулей неправильного (под-)интерпретатора. (XXX Это сложно исправимая ошибка, которая будет устранена в одном из будущих релизов.)4849Также обратите внимание, что использование этой функциональности несовместимо с модулями расширения, такими как PyObjC и ctypes, которые используют API `PyGILState_*()` (и это заложено в самой работе функций `PyGILState_*()`). Простые вещи могут работать, но странное поведение будет постоянно рядом.5051**void `Py_EndInterpreter`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**5253Уничтожает (суб-)интерпретатор, представленный данным состоянием потока. Указанное состояние потока должно быть текущим состоянием потока. См. обсуждение состояний потоков ниже. После возврата из вызова текущее состояние потока равно *NULL*. Все состояния потоков, связанные с этим интерпретатором, уничтожаются. (Глобальная блокировка интерпретатора должна быть захвачена перед вызовом этой функции и остаётся захваченной при возврате.) [`Py_Finalize()`](https://python-all.ru/2.6/c-api/init.html#Py_Finalize) уничтожит все суб-интерпретаторы, которые не были явно уничтожены к этому моменту.5455**void `Py_SetProgramName`(char *\*name*)**5657Эту функцию следует вызывать до первого вызова [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize), если она вообще вызывается. Она сообщает интерпретатору значение аргумента `argv[0]` функции `main()` программы. Это используется [`Py_GetPath()`](https://python-all.ru/2.6/c-api/init.html#Py_GetPath) и некоторыми другими функциями ниже для поиска библиотек времени выполнения Python относительно исполняемого файла интерпретатора. Значение по умолчанию – `'python'`. Аргумент должен указывать на нуль-терминированную строку символов в статической памяти, содержимое которой не будет изменяться в течение выполнения программы. Никакой код в интерпретаторе Python не изменит содержимое этой памяти.5859**char\* `Py_GetProgramName`()**6061Возвращает имя программы, установленное с помощью [`Py_SetProgramName()`](https://python-all.ru/2.6/c-api/init.html#Py_SetProgramName), или значение по умолчанию. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение.6263**char\* `Py_GetPrefix`()**6465Возвращает6667*префикс*6869для установленных платформонезависимых файлов. Он вычисляется с помощью ряда сложных правил на основе имени программы, заданного с помощью7071[`Py_SetProgramName()`](https://python-all.ru/2.6/c-api/init.html#Py_SetProgramName)7273, и некоторых переменных окружения; например, если имя программы –7475`'/usr/local/bin/python'`7677, то префикс –7879`'/usr/local'`8081. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это соответствует переменной8283**prefix**8485в корневом8687`Makefile`8889и аргументу9091*--prefix*9293сценария9495**configure**9697во время сборки. Это значение доступно в коде Python как9899`sys.prefix`100101. Полезно только в Unix. Смотрите также следующую функцию.102103**char\* `Py_GetExecPrefix`()**104105Возвращает *exec-prefix* для установленных *зависимых от платформы* файлов. Он вычисляется с помощью ряда сложных правил на основе имени программы, заданного с помощью [`Py_SetProgramName()`](https://python-all.ru/2.6/c-api/init.html#Py_SetProgramName), и некоторых переменных окружения; например, если имя программы – `'/usr/local/bin/python'`, то exec-prefix – `'/usr/local'`. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это соответствует переменной **exec\_prefix** в корневом `Makefile` и аргументу *--exec-prefix* сценария **configure** во время сборки. Это значение доступно в коде Python как `sys.exec_prefix`. Полезно только в Unix.106107Справочно: exec-prefix отличается от prefix, когда платформозависимые файлы (такие как исполняемые файлы и разделяемые библиотеки) устанавливаются в другое дерево каталогов. В типичной установке платформозависимые файлы могут быть установлены в поддерево `/usr/local/plat`, а платформонезависимые – в `/usr/local`.108109Вообще говоря, платформа – это комбинация семейств аппаратного и программного обеспечения; например, машины Sparc под управлением ОС Solaris 2.x считаются одной платформой, машины Intel под Solaris 2.x – другой, а машины Intel под Linux – третьей. Разные основные версии одной и той же ОС обычно также образуют разные платформы. Операционные системы, отличные от Unix, – это отдельная история; стратегии установки на этих системах настолько различаются, что префикс и exec-prefix не имеют смысла и устанавливаются в пустую строку. Обратите внимание: скомпилированные файлы байт-кода Python не зависят от платформы (но не от версии Python, под которой они были скомпилированы!).110111Системные администраторы знают, как настроить программы **mount** или **automount** для общего доступа к `/usr/local` между платформами, при этом `/usr/local/plat` будет отдельной файловой системой для каждой платформы.112113**char\* `Py_GetProgramFullPath`()**114115Возвращает полное имя исполняемого файла Python; оно вычисляется как побочный эффект вывода пути поиска модулей по умолчанию из имени программы (заданного с помощью [`Py_SetProgramName()`](https://python-all.ru/2.6/c-api/init.html#Py_SetProgramName) выше). Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Значение доступно в коде Python как `sys.executable`.116117**char\* `Py_GetPath`()**118119Возвращает путь поиска модулей по умолчанию; он вычисляется на основе имени программы (заданного с помощью [`Py_SetProgramName()`](https://python-all.ru/2.6/c-api/init.html#Py_SetProgramName) выше) и некоторых переменных окружения. Возвращаемая строка состоит из последовательности имён каталогов, разделённых символом-разделителем, зависящим от платформы. Символ-разделитель – `':'` на Unix и Mac OS X, `';'` на Windows. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Список [`sys.path`](https://python-all.ru/2.6/library/sys.html#sys.path) инициализируется этим значением при запуске интерпретатора; он может быть (и обычно) изменён позже для изменения пути поиска при загрузке модулей.120121**const char\* `Py_GetVersion`()**122123Возвращает версию данного интерпретатора Python. Это строка, которая выглядит примерно так:124125```c126"1.5 (#67, Dec 31 1997, 22:34:28) [GCC 2.7.2.2]"127```128129Первое слово (до первого пробела) – это текущая версия Python; первые три символа – это старшая и младшая версии, разделённые точкой. Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение. Значение доступно из кода Python как `sys.version`.130131**const char\* `Py_GetPlatform`()**132133Возвращает идентификатор платформы для текущей платформы. В Unix он формируется из «официального» имени операционной системы, приведённого к нижнему регистру, с добавлением номера старшей версии; например, для Solaris 2.x (также известной как SunOS 5.x) возвращается `'sunos5'`. На Mac OS X – `'darwin'`. В Windows – `'win'`. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно в коде Python как `sys.platform`.134135**const char\* `Py_GetCopyright`()**136137Возвращает официальную строку авторских прав для текущей версии Python, например138139`'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'`140141Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно в коде Python как `sys.copyright`.142143**const char\* `Py_GetCompiler`()**144145Возвращает указание компилятора, использованного для сборки текущей версии Python, в квадратных скобках, например:146147```c148"[GCC 2.7.2.2]"149```150151Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно в коде Python как часть переменной `sys.version`.152153**const char\* `Py_GetBuildInfo`()**154155Возвращает информацию о номере сборки, дате и времени сборки текущего экземпляра интерпретатора Python, например156157```c158"#67, Aug 1 1997, 22:34:28"159```160161Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно в коде Python как часть переменной `sys.version`.162163**void `PySys_SetArgvEx`(int *argc*, char *\*\*argv*, int *updatepath*)**164165Устанавливает [`sys.argv`](https://python-all.ru/2.6/library/sys.html#sys.argv) на основе *argc* и *argv*. Эти параметры аналогичны тем, что передаются в функцию `main()` программы, с той разницей, что первый элемент должен указывать на исполняемый файл скрипта, а не на исполняемый файл, в который встроен интерпретатор Python. Если запускаемый скрипт отсутствует, первый элемент в *argv* может быть пустой строкой. Если эта функция не сможет инициализировать [`sys.argv`](https://python-all.ru/2.6/library/sys.html#sys.argv), сигнализируется фатальная ошибка с помощью [`Py_FatalError()`](https://python-all.ru/2.6/c-api/sys.html#Py_FatalError).166167Если *updatepath* равен нулю, функция делает только это. Если *updatepath* не равен нулю, функция также изменяет [`sys.path`](https://python-all.ru/2.6/library/sys.html#sys.path) согласно следующему алгоритму:168169- Если в `argv[0]` передано имя существующего скрипта, в начало [`sys.path`](https://python-all.ru/2.6/library/sys.html#sys.path) добавляется абсолютный путь к каталогу, где находится этот скрипт.170- В противном случае (то есть если *argc* равно 0 или `argv[0]` не указывает на существующий файл), в начало [`sys.path`](https://python-all.ru/2.6/library/sys.html#sys.path) добавляется пустая строка, что равносильно добавлению текущего рабочего каталога (`"."`).171172> **Примечание**173>174> Приложениям, встраивающим интерпретатор Python для целей, отличных от выполнения одного скрипта, рекомендуется передавать 0 в качестве *updatepath* и при необходимости изменять [`sys.path`](https://python-all.ru/2.6/library/sys.html#sys.path) самостоятельно. См. [CVE-2008-5983](https://python-all.ru/2.6/c-api/init.html).175>176> В версиях до 2.6.6 того же эффекта можно достичь, вручную удалив первый элемент [`sys.path`](https://python-all.ru/2.6/library/sys.html#sys.path) после вызова [`PySys_SetArgv()`](https://python-all.ru/2.6/c-api/init.html#PySys_SetArgv), например, с помощью:177>178> ```c179> PyRun_SimpleString("import sys; sys.path.pop(0)\n");180> ```181182Новое в версии 2.6.6.183184**void `PySys_SetArgv`(int *argc*, char *\*\*argv*)**185186Эта функция работает как187188[`PySys_SetArgv()`](https://python-all.ru/2.6/c-api/init.html#PySys_SetArgv)189190с параметром191192*updatepath*193194, установленным в 1.195196**void `Py_SetPythonHome`(char *\*home*)**197198Set the default “home” directory, that is, the location of the standard Python libraries. The libraries are searched in199200`home/lib/pythonversion`201202and203204`home/lib/pythonversion`205206. The argument should point to a zero-terminated character string in static storage whose contents will not change for the duration of the program’s execution. No code in the Python interpreter will change the contents of this storage.207208**char\* `Py_GetPythonHome`()**209210Возвращает домашний каталог по умолчанию, то есть значение, установленное предыдущим вызовом211212[`Py_SetPythonHome()`](https://python-all.ru/2.6/c-api/init.html#Py_SetPythonHome)213214, или значение переменной окружения215216[**PYTHONHOME**](https://python-all.ru/2.6/using/cmdline.html#envvar-PYTHONHOME)217218, если она установлена.219220## Состояние потока и глобальная блокировка интерпретатора221222Интерпретатор Python не полностью потокобезопасен. Для поддержки многопоточных программ Python существует глобальная блокировка, называемая *глобальной блокировкой интерпретатора* или *GIL*, которая должна удерживаться текущим потоком перед тем, как он сможет безопасно обращаться к объектам Python. Без этой блокировки даже самые простые операции могут вызывать проблемы в многопоточной программе: например, когда два потока одновременно увеличивают счётчик ссылок одного и того же объекта, счётчик ссылок может быть увеличен только один раз вместо двух.223224Следовательно, существует правило: только поток, захвативший глобальную блокировку интерпретатора, может работать с объектами Python или вызывать функции Python/C API. Для поддержки многопоточных программ на Python интерпретатор регулярно отпускает и снова захватывает блокировку – по умолчанию каждые 100 инструкций байт-кода (это можно изменить с помощью [`sys.setcheckinterval()`](https://python-all.ru/2.6/library/sys.html#sys.setcheckinterval)). Блокировка также отпускается и захватывается вокруг потенциально блокирующих операций ввода-вывода, таких как чтение или запись файла, чтобы другие потоки могли выполняться, пока поток, запросивший ввод-вывод, ожидает завершения операции.225226Интерпретатору Python необходимо хранить некоторую служебную информацию отдельно для каждого потока – для этого используется структура данных, называемая [`PyThreadState`](https://python-all.ru/2.6/c-api/init.html#PyThreadState). Однако существует одна глобальная переменная: указатель на текущую структуру [`PyThreadState`](https://python-all.ru/2.6/c-api/init.html#PyThreadState). До появления *потоковой локальной памяти* (*TLS*) текущее состояние потока приходилось изменять явно.227228В большинстве случаев это достаточно просто. Большая часть кода, работающего с глобальной блокировкой интерпретатора, имеет следующую простую структуру:229230```c231Save the thread state in a local variable.232Release the global interpreter lock.233...Do some blocking I/O operation...234Reacquire the global interpreter lock.235Restore the thread state from the local variable.236```237238Это настолько распространено, что существует пара макросов для упрощения:239240```c241Py_BEGIN_ALLOW_THREADS242...Do some blocking I/O operation...243Py_END_ALLOW_THREADS244```245246Макрос [`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_BEGIN_ALLOW_THREADS) открывает новый блок и объявляет скрытую локальную переменную; макрос [`Py_END_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_END_ALLOW_THREADS) закрывает блок. Ещё одно преимущество использования этих двух макросов в том, что при компиляции Python без поддержки потоков они определены пустыми, что избавляет от манипуляций с состоянием потока и GIL.247248Когда поддержка потоков включена, указанный выше блок раскрывается в следующий код:249250```c251PyThreadState *_save;252253_save = PyEval_SaveThread();254...Do some blocking I/O operation...255PyEval_RestoreThread(_save);256```257258Используя ещё более низкоуровневые примитивы, можно получить примерно тот же эффект следующим образом:259260```c261PyThreadState *_save;262263_save = PyThreadState_Swap(NULL);264PyEval_ReleaseLock();265...Do some blocking I/O operation...266PyEval_AcquireLock();267PyThreadState_Swap(_save);268```269270Существуют некоторые тонкие различия; в частности, [`PyEval_RestoreThread()`](https://python-all.ru/2.6/c-api/init.html#PyEval_RestoreThread) сохраняет и восстанавливает значение глобальной переменной `errno`, поскольку манипуляции с блокировкой не гарантируют, что `errno` останется нетронутым. Кроме того, если поддержка потоков отключена, [`PyEval_SaveThread()`](https://python-all.ru/2.6/c-api/init.html#PyEval_SaveThread) и [`PyEval_RestoreThread()`](https://python-all.ru/2.6/c-api/init.html#PyEval_RestoreThread) не управляют GIL; в этом случае [`PyEval_ReleaseLock()`](https://python-all.ru/2.6/c-api/init.html#PyEval_ReleaseLock) и [`PyEval_AcquireLock()`](https://python-all.ru/2.6/c-api/init.html#PyEval_AcquireLock) недоступны. Это сделано для того, чтобы динамически загружаемые расширения, скомпилированные с включённой поддержкой потоков, могли быть загружены интерпретатором, скомпилированным с отключённой поддержкой потоков.271272Глобальная блокировка интерпретатора используется для защиты указателя на текущее состояние потока. При отпускании блокировки и сохранении состояния потока указатель на текущее состояние потока должен быть получен до того, как блокировка будет отпущена (поскольку другой поток может немедленно захватить блокировку и сохранить своё собственное состояние потока в глобальной переменной). И наоборот, при захвате блокировки и восстановлении состояния потока блокировка должна быть захвачена до сохранения указателя на состояние потока.273274Важно отметить, что при создании потоков из C у них нет глобальной блокировки интерпретатора, а также отсутствует структура данных состояния потока. Такие потоки должны самостоятельно инициализироваться: сначала создать структуру данных состояния потока, затем захватить блокировку и, наконец, сохранить указатель на состояние потока, прежде чем они смогут начать использовать API Python/C. По завершении работы они должны сбросить указатель состояния потока, освободить блокировку и, наконец, освободить структуру данных состояния потока.275276Начиная с версии 2.3, потоки могут использовать функции `PyGILState_*()`, чтобы автоматически выполнять все вышеперечисленные действия. Типичный подход для вызова Python из потока C теперь таков:277278```c279PyGILState_STATE gstate;280gstate = PyGILState_Ensure();281282/* Выполнить действия Python здесь. */283result = CallSomeFunction();284/* результат вычисления */285286/* Освободить поток. После этой точки API Python не допускается. */287PyGILState_Release(gstate);288```289290Обратите внимание, что функции `PyGILState_*()` предполагают наличие только одного глобального интерпретатора (созданного автоматически вызовом [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize)). Python по-прежнему поддерживает создание дополнительных интерпретаторов (с помощью [`Py_NewInterpreter()`](https://python-all.ru/2.6/c-api/init.html#Py_NewInterpreter)), но смешивание нескольких интерпретаторов и API `PyGILState_*()` не поддерживается.291292Ещё один важный момент, касающийся потоков – это их поведение при вызове C-функции `fork()`. На большинстве систем с `fork()` после разветвления (fork) процесса существовать будет только тот поток, который вызвал fork. Это также означает, что любые блокировки, удерживаемые другими потоками, никогда не будут освобождены. Python решает эту проблему для [`os.fork()`](https://python-all.ru/2.6/library/os.html#os.fork), захватывая используемые им внутренние блокировки перед fork и освобождая их после. Кроме того, он сбрасывает любые [*объекты блокировок*](https://python-all.ru/2.6/library/threading.html#lock-objects) в дочернем процессе. При расширении или встраивании Python нет способа сообщить Python о дополнительных (не-Python) блокировках, которые необходимо захватить перед fork или сбросить после. Для достижения того же эффекта потребуется использовать системные средства, такие как `posix_atfork()`. Кроме того, при расширении или встраивании Python прямой вызов `fork()` вместо вызова через [`os.fork()`](https://python-all.ru/2.6/library/os.html#os.fork) (и возврат в Python или вызов кода Python) может привести к взаимоблокировке из-за того, что одна из внутренних блокировок Python остаётся удерживаемой потоком, который после fork перестаёт существовать. [`PyOS_AfterFork()`](https://python-all.ru/2.6/c-api/sys.html#PyOS_AfterFork) пытается сбросить необходимые блокировки, но это удаётся не всегда.293294**`PyInterpreterState`**295296Эта структура данных представляет состояние, совместно используемое несколькими взаимодействующими потоками. Потоки, принадлежащие одному интерпретатору, разделяют администрирование модулей и несколько других внутренних элементов. В этой структуре нет открытых членов.297298Потоки, принадлежащие разным интерпретаторам, изначально не разделяют ничего, кроме состояния процесса, такого как доступная память, открытые файловые дескрипторы и т.п. Глобальная блокировка интерпретатора также разделяется всеми потоками, независимо от того, какому интерпретатору они принадлежат.299300**`PyThreadState`**301302Эта структура данных представляет состояние одного потока. Единственная открытая (public) переменная-член –303304[`PyInterpreterState *`](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState)305306`interp`307308, которая указывает на состояние интерпретатора этого потока.309310**void `PyEval_InitThreads`()**311312Инициализирует и захватывает глобальную блокировку интерпретатора. Она должна вызываться в главном потоке перед созданием второго потока или выполнением любых других операций с потоками, таких как [`PyEval_ReleaseLock()`](https://python-all.ru/2.6/c-api/init.html#PyEval_ReleaseLock) или `PyEval_ReleaseThread(tstate)`. Её не нужно вызывать перед [`PyEval_SaveThread()`](https://python-all.ru/2.6/c-api/init.html#PyEval_SaveThread) или [`PyEval_RestoreThread()`](https://python-all.ru/2.6/c-api/init.html#PyEval_RestoreThread).313314При повторном вызове эта функция ничего не делает. Её можно безопасно вызывать до [`Py_Initialize()`](https://python-all.ru/2.6/c-api/init.html#Py_Initialize).315316Когда существует только главный поток, операции с GIL не нужны. Это обычная ситуация (большинство программ на Python не использует потоки), и операции блокировки немного замедляют интерпретатор. Поэтому блокировка изначально не создаётся. Эта ситуация эквивалентна захвату блокировки: при наличии единственного потока все обращения к объектам безопасны. Поэтому, когда эта функция инициализирует глобальную блокировку интерпретатора, она также её захватывает. Прежде чем модуль Python [`thread`](https://python-all.ru/2.6/library/thread.html#module-thread) создаст новый поток, он, зная, что либо блокировка у него уже есть, либо она ещё не создана, вызывает [`PyEval_InitThreads()`](https://python-all.ru/2.6/c-api/init.html#PyEval_InitThreads). Когда этот вызов завершается, гарантируется, что блокировка создана и вызывающий поток её захватил.317318**Не**безопасно вызывать эту функцию, когда неизвестно, какой поток (если таковой есть) в данный момент удерживает глобальную блокировку интерпретатора.319320Эта функция недоступна, если поддержка потоков отключена на этапе компиляции.321322**int `PyEval_ThreadsInitialized`()**323324Возвращает ненулевое значение, если [`PyEval_InitThreads()`](https://python-all.ru/2.6/c-api/init.html#PyEval_InitThreads) была вызвана. Эту функцию можно вызывать без захвата GIL, и поэтому её можно использовать, чтобы избежать вызовов API блокировки при однопоточной работе. Функция недоступна, если поддержка потоков отключена во время компиляции.325326Новое в версии 2.4.327328**void `PyEval_AcquireLock`()**329330Захватывает глобальную блокировку интерпретатора. Блокировка должна быть создана ранее. Если этот поток уже владеет блокировкой, возникнет взаимная блокировка. Эта функция недоступна, если поддержка потоков отключена при компиляции.331332**void `PyEval_ReleaseLock`()**333334Освобождает глобальную блокировку интерпретатора. Блокировка должна быть создана ранее. Эта функция недоступна, если поддержка потоков отключена при компиляции.335336**void `PyEval_AcquireThread`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**337338Захватывает глобальную блокировку интерпретатора и устанавливает текущее состояние потока в339340*tstate*341342, которое не должно быть343344*NULL*345346. Блокировка должна быть создана ранее. Если этот поток уже владеет блокировкой, возникнет взаимная блокировка. Эта функция недоступна, если поддержка потоков отключена при компиляции.347348**void `PyEval_ReleaseThread`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**349350Сбрасывает текущее состояние потока в351352*NULL*353354и освобождает глобальную блокировку интерпретатора. Блокировка должна быть создана ранее и должна удерживаться текущим потоком. Аргумент355356*tstate*357358, который не должен быть359360*NULL*361362, используется только для проверки, что он представляет текущее состояние потока – если нет, сообщается о фатальной ошибке. Эта функция недоступна, если поддержка потоков отключена при компиляции.363364**[PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState)\* `PyEval_SaveThread`()**365366Освобождает глобальную блокировку интерпретатора (если она создана и поддержка потоков включена) и сбрасывает состояние потока в367368*NULL*369370, возвращая предыдущее состояние потока (которое не равно371372*NULL*373374). Если блокировка была создана, текущий поток должен был захватить её. (Эта функция доступна, даже если поддержка потоков отключена на этапе компиляции.)375376**void `PyEval_RestoreThread`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**377378Захватывает глобальную блокировку интерпретатора (если она создана и поддержка потоков включена) и устанавливает состояние потока в379380*tstate*381382, который не должен быть383384*NULL*385386. Если блокировка была создана, текущий поток не должен был захватить её, иначе возникнет взаимоблокировка. (Эта функция доступна, даже если поддержка потоков отключена на этапе компиляции.)387388**void `PyEval_ReInitThreads`()**389390Эта функция вызывается из391392[`PyOS_AfterFork()`](https://python-all.ru/2.6/c-api/sys.html#PyOS_AfterFork)393394, чтобы гарантировать, что вновь созданные дочерние процессы не удерживают блокировки, относящиеся к потокам, которые не выполняются в дочернем процессе.395396Следующие макросы обычно используются без точки с запятой в конце; примеры использования можно найти в дистрибутиве исходного кода Python.397398**`Py_BEGIN_ALLOW_THREADS`**399400Этот макрос раскрывается в401402`{ PyThreadState *_save; _save = PyEval_SaveThread();`403404. Обратите внимание, что он содержит открывающую фигурную скобку; он должен быть уравновешен последующим макросом405406[`Py_END_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_END_ALLOW_THREADS)407408. См. выше обсуждение этого макроса. Ничего не делает, если поддержка потоков отключена во время компиляции.409410**`Py_END_ALLOW_THREADS`**411412Этот макрос раскрывается в413414`PyEval_RestoreThread(_save); }`415416. Обратите внимание, что он содержит закрывающую фигурную скобку; он должен быть уравновешен предшествующим макросом417418[`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_BEGIN_ALLOW_THREADS)419420. См. выше обсуждение этого макроса. Ничего не делает, если поддержка потоков отключена во время компиляции.421422**`Py_BLOCK_THREADS`**423424Этот макрос раскрывается в425426`PyEval_RestoreThread(_save);`427428: он эквивалентен429430[`Py_END_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_END_ALLOW_THREADS)431432без закрывающей фигурной скобки. Он не выполняет никаких действий, если поддержка потоков отключена на этапе компиляции.433434**`Py_UNBLOCK_THREADS`**435436Этот макрос раскрывается в437438`_save = PyEval_SaveThread();`439440: он эквивалентен441442[`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_BEGIN_ALLOW_THREADS)443444без открывающей фигурной скобки и объявления переменной. Он не выполняет никаких действий, если поддержка потоков отключена на этапе компиляции.445446Все следующие функции доступны только при включенной поддержке потоков во время компиляции и должны вызываться только после создания глобальной блокировки интерпретатора.447448**[PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState)\* `PyInterpreterState_New`()**449450Создаёт новый объект состояния интерпретатора. Глобальная блокировка интерпретатора может не удерживаться, но может удерживаться, если необходимо сериализовать вызовы этой функции.451452**void `PyInterpreterState_Clear`([PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState) *\*interp*)**453454Сбрасывает всю информацию в объекте состояния интерпретатора. Глобальная блокировка интерпретатора должна удерживаться.455456**void `PyInterpreterState_Delete`([PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState) *\*interp*)**457458Уничтожает объект состояния интерпретатора. Глобальная блокировка интерпретатора может не удерживаться. Состояние интерпретатора должно быть сброшено предварительным вызовом459460[`PyInterpreterState_Clear()`](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState_Clear)461462.463464**[PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState)\* `PyThreadState_New`([PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState) *\*interp*)**465466Создаёт новый объект состояния потока, принадлежащий данному объекту интерпретатора. Глобальная блокировка интерпретатора может не удерживаться, но может удерживаться, если необходимо сериализовать вызовы этой функции.467468**void `PyThreadState_Clear`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**469470Сбрасывает всю информацию в объекте состояния потока. Глобальная блокировка интерпретатора должна удерживаться.471472**void `PyThreadState_Delete`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**473474Уничтожает объект состояния потока. Глобальная блокировка интерпретатора может не удерживаться. Состояние потока должно быть сброшено предварительным вызовом475476[`PyThreadState_Clear()`](https://python-all.ru/2.6/c-api/init.html#PyThreadState_Clear)477478.479480**[PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState)\* `PyThreadState_Get`()**481482Возвращает текущее состояние потока. Должна быть захвачена глобальная блокировка интерпретатора. Если текущее состояние потока равно483484*NULL*485486, возникает фатальная ошибка (таким образом, вызывающему коду не нужно проверять на487488*NULL*489490).491492**[PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState)\* `PyThreadState_Swap`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**493494Заменяет текущее состояние потока на состояние потока, заданное аргументом495496*tstate*497498, который может быть499500*NULL*501502. Глобальная блокировка интерпретатора должна быть удержана.503504**[PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject)\* `PyThreadState_GetDict`()**505506*Возвращаемое значение: заимствованная ссылка.*507508Возвращает словарь, в котором расширения могут хранить информацию о состоянии, специфичном для потока. Каждое расширение должно использовать уникальный ключ для хранения состояния в словаре. Эту функцию можно вызывать, даже если текущее состояние потока недоступно. Если эта функция возвращает *NULL*, исключение не было возбуждено, и вызывающий код должен считать, что текущее состояние потока недоступно.509510Изменено в версии 2.3: Ранее это можно было вызывать только при активном текущем потоке, и *NULL* означал, что было возбуждено исключение.511512**int `PyThreadState_SetAsyncExc`(long *id*, [PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*exc*)**513514Асинхронно возбуждает исключение в потоке. Аргумент *id* – это идентификатор потока целевого потока; *exc* – объект исключения, которое нужно возбудить. Эта функция не похищает никаких ссылок на *exc*. Чтобы предотвратить наивное злоупотребление, вы должны написать собственное расширение C для её вызова. Должна вызываться с захваченным GIL. Возвращает количество изменённых состояний потока; обычно это единица, но будет нулём, если идентификатор потока не найден. Если *exc* равно `NULL`, то ожидающее исключение (если есть) для потока очищается. Эта функция не возбуждает исключений.515516Новое в версии 2.3.517518**PyGILState\_STATE `PyGILState_Ensure`()**519520Гарантирует, что текущий поток готов вызывать Python C API независимо от текущего состояния Python или глобальной блокировки интерпретатора. Может вызываться потоком сколько угодно раз, при условии, что каждый вызов соответствует вызову [`PyGILState_Release()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Release). В общем случае между вызовами [`PyGILState_Ensure()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Ensure) и [`PyGILState_Release()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Release) можно использовать другие API, связанные с потоками, при условии, что состояние потока будет восстановлено до предыдущего перед вызовом Release(). Например, допустимо обычное использование макросов [`Py_BEGIN_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_BEGIN_ALLOW_THREADS) и [`Py_END_ALLOW_THREADS`](https://python-all.ru/2.6/c-api/init.html#Py_END_ALLOW_THREADS).521522Возвращаемое значение – непрозрачный «дескриптор» состояния потока на момент вызова [`PyGILState_Ensure()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Ensure), и его необходимо передать в [`PyGILState_Release()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Release), чтобы гарантировать, что Python останется в том же состоянии. Хотя рекурсивные вызовы разрешены, эти дескрипторы *нельзя* разделять – каждый уникальный вызов [`PyGILState_Ensure()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Ensure) должен сохранить дескриптор для своего вызова [`PyGILState_Release()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Release).523524При возврате из функции текущий поток будет удерживать GIL. Сбой является фатальной ошибкой.525526Новое в версии 2.3.527528**void `PyGILState_Release`(PyGILState\_STATE)**529530Освобождает все ранее захваченные ресурсы. После этого вызова состояние Python будет таким же, как до соответствующего вызова [`PyGILState_Ensure()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Ensure) (но обычно это состояние неизвестно вызывающей стороне, отсюда и использование GILState API.)531532Каждый вызов [`PyGILState_Ensure()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Ensure) должен быть уравновешен вызовом [`PyGILState_Release()`](https://python-all.ru/2.6/c-api/init.html#PyGILState_Release) в том же потоке.533534Новое в версии 2.3.535536## Профилирование и трассировка537538Интерпретатор Python предоставляет низкоуровневую поддержку для подключения средств профилирования и трассировки выполнения. Они используются в инструментах профилирования, отладки и анализа покрытия.539540Начиная с Python 2.2, реализация этого механизма была существенно переработана, и был добавлен интерфейс на C. Этот интерфейс на C позволяет коду профилирования или трассировки избежать накладных расходов на вызов через вызываемые объекты уровня Python, выполняя вместо этого прямой вызов функции на C. Основные атрибуты механизма не изменились; интерфейс позволяет устанавливать функции трассировки для каждого потока, и базовые события, сообщаемые функции трассировки, остались теми же, что сообщались функциям трассировки уровня Python в предыдущих версиях.541542**int `(*Py_tracefunc)`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*obj*, PyFrameObject *\*frame*, int *what*, [PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*arg*)**543544Тип функции трассировки, зарегистрированной с помощью [`PyEval_SetProfile()`](https://python-all.ru/2.6/c-api/init.html#PyEval_SetProfile) и [`PyEval_SetTrace()`](https://python-all.ru/2.6/c-api/init.html#PyEval_SetTrace). Первый параметр – это объект, переданный функции регистрации как *obj*, *frame* – объект кадра, к которому относится событие, *what* – одна из констант [`PyTrace_CALL`](https://python-all.ru/2.6/c-api/init.html#PyTrace_CALL), [`PyTrace_EXCEPTION`](https://python-all.ru/2.6/c-api/init.html#PyTrace_EXCEPTION), [`PyTrace_LINE`](https://python-all.ru/2.6/c-api/init.html#PyTrace_LINE), [`PyTrace_RETURN`](https://python-all.ru/2.6/c-api/init.html#PyTrace_RETURN), [`PyTrace_C_CALL`](https://python-all.ru/2.6/c-api/init.html#PyTrace_C_CALL), [`PyTrace_C_EXCEPTION`](https://python-all.ru/2.6/c-api/init.html#PyTrace_C_EXCEPTION), или [`PyTrace_C_RETURN`](https://python-all.ru/2.6/c-api/init.html#PyTrace_C_RETURN), а *arg* зависит от значения *what*:545546| Значение *what* | Смысл *arg* |547| --- | --- |548| [`PyTrace_CALL`](https://python-all.ru/2.6/c-api/init.html#PyTrace_CALL) | Всегда *NULL*. |549| [`PyTrace_EXCEPTION`](https://python-all.ru/2.6/c-api/init.html#PyTrace_EXCEPTION) | Информация об исключении, возвращаемая [`sys.exc_info()`](https://python-all.ru/2.6/library/sys.html#sys.exc_info). |550| [`PyTrace_LINE`](https://python-all.ru/2.6/c-api/init.html#PyTrace_LINE) | Всегда *NULL*. |551| [`PyTrace_RETURN`](https://python-all.ru/2.6/c-api/init.html#PyTrace_RETURN) | Значение, возвращаемое вызывающему. |552| [`PyTrace_C_CALL`](https://python-all.ru/2.6/c-api/init.html#PyTrace_C_CALL) | Имя вызываемой функции. |553| [`PyTrace_C_EXCEPTION`](https://python-all.ru/2.6/c-api/init.html#PyTrace_C_EXCEPTION) | Всегда *NULL*. |554| [`PyTrace_C_RETURN`](https://python-all.ru/2.6/c-api/init.html#PyTrace_C_RETURN) | Всегда *NULL*. |555556**int `PyTrace_CALL`**557558Значение параметра559560*what*561562функции563564[`Py_tracefunc`](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc)565566, когда сообщается о новом вызове функции или метода, или о новом входе в генератор. Обратите внимание, что создание итератора для функции-генератора не сообщается, поскольку нет передачи управления байт-коду Python в соответствующем фрейме.567568**int `PyTrace_EXCEPTION`**569570Значение параметра571572*what*573574функции575576[`Py_tracefunc`](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc)577578, когда возникло исключение. Функция обратного вызова вызывается с этим значением для579580*what*581582после обработки любого байт-кода, после которого исключение устанавливается в выполняемом фрейме. В результате, когда распространение исключения вызывает разворачивание стека Python, обратный вызов вызывается при возврате в каждый фрейм по мере распространения исключения. Только функции трассировки получают эти события; профилировщику они не нужны.583584**int `PyTrace_LINE`**585586Значение, передаваемое в качестве параметра587588*what*589590в трассировочную функцию (но не в профилирующую функцию), когда сообщается о событии номера строки.591592**int `PyTrace_RETURN`**593594Значение параметра595596*what*597598функций599600[`Py_tracefunc`](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc)601602, когда вызов возвращается без распространения исключения.603604**int `PyTrace_C_CALL`**605606Значение параметра607608*what*609610функций611612[`Py_tracefunc`](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc)613614, когда функция на C собирается быть вызванной.615616**int `PyTrace_C_EXCEPTION`**617618Значение параметра619620*what*621622для функций623624[`Py_tracefunc`](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc)625626, когда C-функция вызвала исключение.627628**int `PyTrace_C_RETURN`**629630Значение параметра631632*what*633634функций635636[`Py_tracefunc`](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc)637638, когда функция на C вернулась.639640**void `PyEval_SetProfile`([Py\_tracefunc](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc) *func*, [PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*obj*)**641642Устанавливает функцию профилировщика в643644*func*645646. Параметр647648*obj*649650передаётся функции в качестве первого аргумента и может быть любым объектом Python или651652*NULL*653654. Если функции профилировщика требуется поддерживать состояние, использование разных значений655656*obj*657658для каждого потока предоставляет удобное и потокобезопасное место для его хранения. Функция профилировщика вызывается для всех отслеживаемых событий, кроме событий с номерами строк.659660**void `PyEval_SetTrace`([Py\_tracefunc](https://python-all.ru/2.6/c-api/init.html#Py_tracefunc) *func*, [PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*obj*)**661662Устанавливает функцию трассировки в663664*func*665666. Это похоже на667668[`PyEval_SetProfile()`](https://python-all.ru/2.6/c-api/init.html#PyEval_SetProfile)669670, за исключением того, что функция трассировки получает события номеров строк.671672**[PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject)\* `PyEval_GetCallStats`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*self*)**673674Возвращает кортеж счётчиков вызовов функций. Для позиций в кортеже определены константы:675676| Имя | Значение |677| --- | --- |678| `PCALL_ALL` | 0 |679| `PCALL_FUNCTION` | 1 |680| `PCALL_FAST_FUNCTION` | 2 |681| `PCALL_FASTER_FUNCTION` | 3 |682| `PCALL_METHOD` | 4 |683| `PCALL_BOUND_METHOD` | 5 |684| `PCALL_CFUNCTION` | 6 |685| `PCALL_TYPE` | 7 |686| `PCALL_GENERATOR` | 8 |687| `PCALL_OTHER` | 9 |688| `PCALL_POP` | 10 |689690`PCALL_FAST_FUNCTION` означает, что создавать кортеж аргументов не требуется. `PCALL_FASTER_FUNCTION` означает, что используется код быстрой настройки фрейма.691692Если есть вызов метода, который можно оптимизировать, изменив кортеж аргументов и вызвав функцию напрямую, он записывается дважды.693694Эта функция доступна только при компиляции Python с определённым `CALL_PROFILE`.695696## Поддержка расширенного отладчика697698Эти функции предназначены только для использования расширенными инструментами отладки.699700**[PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState)\* `PyInterpreterState_Head`()**701702Возвращает объект состояния интерпретатора, находящийся в начале списка всех таких объектов.703704Новое в версии 2.2.705706**[PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState)\* `PyInterpreterState_Next`([PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState) *\*interp*)**707708Возвращает следующий объект состояния интерпретатора после *interp* из списка всех таких объектов.709710Новое в версии 2.2.711712**[PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) \* `PyInterpreterState_ThreadHead`([PyInterpreterState](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState) *\*interp*)**713714Возвращает указатель на первый объект [`PyThreadState`](https://python-all.ru/2.6/c-api/init.html#PyThreadState) в списке\\nпотоков, связанных с интерпретатором *interp*.715716Новое в версии 2.2.717718**[PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState)\* `PyThreadState_Next`([PyThreadState](https://python-all.ru/2.6/c-api/init.html#PyThreadState) *\*tstate*)**719720Возвращает следующий объект состояния потока после *tstate* из списка всех таких объектов, принадлежащих одному и тому же объекту [`PyInterpreterState`](https://python-all.ru/2.6/c-api/init.html#PyInterpreterState).721722Новое в версии 2.2.723