Инициализация, финализация и потоки

См. также Python Initialization Configuration.

Перед инициализацией Python

В приложении, встраивающем Python, функция Py_Initialize() должна быть вызвана перед использованием любых других функций Python/C API; за исключением нескольких функций и global configuration variables.

Следующие функции можно безопасно вызывать до инициализации Python:

Примечание

Следующие функции не должны вызываться перед Py_Initialize(): Py_EncodeLocale(), Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix(), Py_GetProgramFullPath(), Py_GetPythonHome(), Py_GetProgramName() и PyEval_InitThreads().

Глобальные переменные конфигурации

В Python есть переменные глобальной конфигурации для управления различными функциями и опциями. По умолчанию этими флагами управляет command line options.

Когда флаг устанавливается опцией, значение флага равно количеству раз, когда опция была установлена. Например, -b устанавливает Py_BytesWarningFlag в 1, а -bb устанавливает Py_BytesWarningFlag в 2.

int Py_BytesWarningFlag

Выдавать предупреждение при сравнении bytes или bytearray с str или bytes с int. Выдать ошибку, если больше или равно 2.

Устанавливается опцией -b.

int Py_DebugFlag

Включить отладочный вывод парсера (только для экспертов, в зависимости от опций компиляции).

Устанавливается опцией -d и переменной окружения PYTHONDEBUG.

int Py_DontWriteBytecodeFlag

Если установлено ненулевое значение, Python не будет пытаться записывать файлы .pyc при импорте исходных модулей.

Устанавливается опцией -B и переменной окружения PYTHONDONTWRITEBYTECODE.

int Py_FrozenFlag

Подавление сообщений об ошибках при вычислении пути поиска модуля в Py_GetPath().

Частный флаг, используемый программами _freeze_importlib и frozenmain.

int Py_HashRandomizationFlag

Устанавливается в 1, если переменная окружения PYTHONHASHSEED установлена в непустую строку.

Если флаг ненулевой, прочитайте переменную окружения PYTHONHASHSEED для инициализации секретного хэш-семени.

int Py_IgnoreEnvironmentFlag

Игнорируйте все переменные окружения PYTHON*, например PYTHONPATH и PYTHONHOME, которые могут быть установлены.

Устанавливается опциями -E и -I.

int Py_InspectFlag

Если в качестве первого аргумента передается сценарий или используется опция -c, после выполнения сценария или команды перейдите в интерактивный режим, даже если sys.stdin не является терминалом.

Устанавливается опцией -i и переменной окружения PYTHONINSPECT.

int Py_InteractiveFlag

Устанавливается опцией -i.

int Py_IsolatedFlag

Запустите Python в изолированном режиме. В изолированном режиме sys.path не содержит ни каталога скрипта, ни каталога site-packages пользователя.

Устанавливается опцией -I.

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

int Py_LegacyWindowsFSEncodingFlag

Если флаг ненулевой, используйте для mbcs кодировку replace вместо кодировки UTF-8 с обработчиком ошибок surrogatepass для filesystem encoding and error handler.

Устанавливается в 1, если переменная окружения PYTHONLEGACYWINDOWSFSENCODING установлена в непустую строку.

Более подробную информацию см. в разделе PEP 529.

Availability: Windows.

int Py_LegacyWindowsStdioFlag

Если флаг ненулевой, используйте io.FileIO вместо WindowsConsoleIO для стандартных потоков sys.

Устанавливается в 1, если переменная окружения PYTHONLEGACYWINDOWSSTDIO установлена в непустую строку.

Более подробную информацию см. в разделе PEP 528.

Availability: Windows.

int Py_NoSiteFlag

Отключите импорт модуля site и зависящие от сайта манипуляции с sys.path, которые он влечет за собой. Также отключите эти манипуляции, если site будет явно импортирован позже (вызовите site.main(), если хотите, чтобы они были запущены).

Устанавливается опцией -S.

int Py_NoUserSiteDirectory

Не добавляйте user site-packages directory к sys.path.

Устанавливается опциями -s и -I, а также переменной окружения PYTHONNOUSERSITE.

int Py_OptimizeFlag

Устанавливается опцией -O и переменной окружения PYTHONOPTIMIZE.

int Py_QuietFlag

Не отображайте сообщения об авторских правах и версии даже в интерактивном режиме.

Устанавливается опцией -q.

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

int Py_UnbufferedStdioFlag

Заставить потоки stdout и stderr быть небуферизованными.

Устанавливается опцией -u и переменной окружения PYTHONUNBUFFERED.

int Py_VerboseFlag

Выводит сообщение при каждой инициализации модуля, показывая место (имя файла или встроенного модуля), из которого он загружен. Если больше или равно 2, выведите сообщение для каждого файла, который проверяется при поиске модуля. Также предоставляет информацию об очистке модуля при выходе.

Устанавливается опцией -v и переменной окружения PYTHONVERBOSE.

Инициализация и завершение работы интерпретатора

void Py_Initialize()
Part of the Stable ABI.

Инициализация интерпретатора Python. В приложении, встраивающем Python, эта функция должна вызываться перед использованием любых других функций Python/C API; несколько исключений см. в Before Python Initialization.

Это инициализирует таблицу загруженных модулей (sys.modules) и создает фундаментальные модули builtins, __main__ и sys. Он также инициализирует путь поиска модулей (sys.path). Он не устанавливает sys.argv; для этого используйте PySys_SetArgvEx(). При повторном вызове (без первого вызова Py_FinalizeEx()) эта функция не работает. Возвращаемого значения нет; при неудачной инициализации происходит фатальная ошибка.

Примечание

В Windows изменяет режим консоли с O_TEXT на O_BINARY, что также повлияет на не-Python использование консоли с помощью C Runtime.

void Py_InitializeEx(int initsigs)
Part of the Stable ABI.

Эта функция работает как Py_Initialize(), если initsigs равно 1. Если initsigs равно 0, то она пропускает инициализационную регистрацию обработчиков сигналов, что может быть полезно при встраивании Python.

int Py_IsInitialized()
Part of the Stable ABI.

Возвращает true (ненулевое значение), если интерпретатор Python был инициализирован, false (нулевое значение), если нет. После вызова Py_FinalizeEx() возвращается false, пока Py_Initialize() не будет вызван снова.

int Py_FinalizeEx()
Part of the Stable ABI since version 3.6.

Отмените все инициализации, сделанные Py_Initialize() и последующее использование функций Python/C API, и уничтожьте все подинтерпретаторы (см. Py_NewInterpreter() ниже), которые были созданы и еще не уничтожены после последнего вызова Py_Initialize(). В идеале, при этом освобождается вся память, выделенная интерпретатору Python. При повторном вызове (без предварительного вызова Py_Initialize()) эта функция не работает. Обычно возвращаемое значение 0. Если при финализации (очистке буферизованных данных) возникли ошибки, возвращается -1.

Эта функция предоставляется по нескольким причинам. Встраиваемое приложение может захотеть перезапустить Python без необходимости перезапуска самого приложения. Приложение, загрузившее интерпретатор Python из динамически загружаемой библиотеки (или DLL), может захотеть освободить всю память, выделенную Python, перед выгрузкой DLL. Во время поиска утечек памяти в приложении разработчик может захотеть освободить всю память, выделенную Python, перед выходом из приложения.

Ошибки и предостережения: Уничтожение модулей и объектов в модулях происходит в случайном порядке; это может привести к сбою деструкторов (методов __del__()), если они зависят от других объектов (даже функций) или модулей. Динамически загруженные модули расширения, загруженные Python, не выгружаются. Небольшие объемы памяти, выделенные интерпретатором Python, могут не освобождаться (если вы обнаружили утечку, пожалуйста, сообщите об этом). Память, связанная круговыми ссылками между объектами, не освобождается. Некоторая память, выделенная модулями расширения, может быть не освобождена. Некоторые расширения могут работать некорректно, если их процедура инициализации вызывается более одного раза; это может произойти, если приложение вызывает Py_Initialize() и Py_FinalizeEx() более одного раза.

Вызывает auditing event cpython._PySys_ClearAuditHooks без аргументов.

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

void Py_Finalize()
Part of the Stable ABI.

Это обратно совместимая версия Py_FinalizeEx(), которая не учитывает возвращаемое значение.

Параметры всего процесса

int Py_SetStandardStreamEncoding(const char *encoding, const char *errors)

Эта функция должна быть вызвана до Py_Initialize(), если она вообще вызывается. Она определяет, какую кодировку и обработку ошибок использовать со стандартным IO, с теми же значениями, что и в str.encode().

Она переопределяет значения PYTHONIOENCODING и позволяет встраивать код для управления кодировкой ввода-вывода, когда переменная окружения не работает.

encoding и/или errors могут NULL использовать PYTHONIOENCODING и/или значения по умолчанию (в зависимости от других настроек).

Обратите внимание, что sys.stderr всегда использует обработчик ошибок «backslashreplace», независимо от этой (или любой другой) настройки.

Если вызывается Py_FinalizeEx(), то эту функцию нужно будет вызвать снова, чтобы повлиять на последующие вызовы Py_Initialize().

Возвращает 0 в случае успеха, ненулевое значение при ошибке (например, вызов после того, как интерпретатор уже был инициализирован).

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

void Py_SetProgramName(const wchar_t *name)
Part of the Stable ABI.

Эта функция должна быть вызвана перед первым вызовом Py_Initialize(), если она вообще вызывается. Она сообщает интерпретатору значение аргумента argv[0] к функции main() программы (преобразованное в широкие символы). Это значение используется Py_GetPath() и некоторыми другими функциями ниже для поиска библиотек времени выполнения Python относительно исполняемого файла интерпретатора. По умолчанию используется значение 'python'. Аргумент должен указывать на широкую символьную строку с нулевым окончанием в статическом хранилище, содержимое которой не будет меняться в течение всего времени выполнения программы. Никакой код в интерпретаторе Python не будет изменять содержимое этого хранилища.

Используйте Py_DecodeLocale() для декодирования байтовой строки, чтобы получить строку wchar_*.

wchar *Py_GetProgramName()
Part of the Stable ABI.

Возвращает имя программы, заданное с помощью Py_SetProgramName(), или значение по умолчанию. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение.

Эта функция не должна вызываться до Py_Initialize(), иначе она возвращает NULL.

Изменено в версии 3.10: Теперь она возвращает NULL, если вызвана до Py_Initialize().

wchar_t *Py_GetPrefix()
Part of the Stable ABI.

Возвращает префикс для установленных платформонезависимых файлов. Он определяется по ряду сложных правил из имени программы, заданного с помощью Py_SetProgramName() и некоторых переменных окружения; например, если имя программы '/usr/local/bin/python', то префикс будет '/usr/local'. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Это соответствует переменной prefix в верхнем уровне Makefile и аргументу --prefix в сценарии configure во время сборки. Значение доступно для кода Python как sys.prefix. Она полезна только на Unix. См. также следующую функцию.

Эта функция не должна вызываться до Py_Initialize(), иначе она возвращает NULL.

Изменено в версии 3.10: Теперь она возвращает NULL, если вызвана до Py_Initialize().

wchar_t *Py_GetExecPrefix()
Part of the Stable ABI.

Возвращает exec-prefix для установленных платформенно-зависимых файлов. Он определяется по ряду сложных правил из имени программы, заданного с помощью Py_SetProgramName() и некоторых переменных окружения; например, если имя программы '/usr/local/bin/python', то exec-префикс будет '/usr/local'. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Это соответствует переменной exec_prefix на верхнем уровне Makefile и аргументу --exec-prefix скрипта configure во время сборки. Значение доступно для кода Python как sys.exec_prefix. Оно полезно только на Unix.

Общие сведения: Префикс exec отличается от префикса, когда платформозависимые файлы (такие как исполняемые файлы и разделяемые библиотеки) устанавливаются в другое дерево каталогов. В типичной установке платформозависимые файлы могут быть установлены в поддерево /usr/local/plat, а платформонезависимые - в /usr/local.

Вообще говоря, платформа - это сочетание аппаратного и программного обеспечения, например, машины Sparc под управлением операционной системы Solaris 2.x считаются одной платформой, но машины Intel под управлением Solaris 2.x - это другая платформа, а машины Intel под управлением Linux - еще одна платформа. Различные основные редакции одной и той же операционной системы, как правило, также образуют разные платформы. Операционные системы не-Unix - это совсем другая история; стратегии установки в этих системах настолько различны, что префикс и exec-prefix не имеют смысла и устанавливаются в пустую строку. Обратите внимание, что скомпилированные файлы байткода Python независимы от платформы (но не независимы от версии Python, под которую они были скомпилированы!).

Системные администраторы будут знать, как настроить программы mount или automount для совместного использования /usr/local между платформами, при этом /usr/local/plat будет отдельной файловой системой для каждой платформы.

Эта функция не должна вызываться до Py_Initialize(), иначе она возвращает NULL.

Изменено в версии 3.10: Теперь она возвращает NULL, если вызвана до Py_Initialize().

wchar_t *Py_GetProgramFullPath()
Part of the Stable ABI.

Возвращает полное имя программы исполняемого файла Python; оно вычисляется как побочный эффект выведения пути поиска модуля по умолчанию из имени программы (заданного Py_SetProgramName() выше). Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как sys.executable.

Эта функция не должна вызываться до Py_Initialize(), иначе она возвращает NULL.

Изменено в версии 3.10: Теперь она возвращает NULL, если вызвана до Py_Initialize().

wchar_t *Py_GetPath()
Part of the Stable ABI.

Возвращает путь поиска модуля по умолчанию; он вычисляется из имени программы (заданного выше Py_SetProgramName()) и некоторых переменных окружения. Возвращаемая строка состоит из серии имен каталогов, разделенных разделительным символом, зависящим от платформы. Символ разделителя - ':' в Unix и macOS, ';' в Windows. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Список sys.path инициализируется этим значением при запуске интерпретатора; позже его можно (и обычно так и происходит) изменить, чтобы изменить путь поиска для загрузки модулей.

Эта функция не должна вызываться до Py_Initialize(), иначе она возвращает NULL.

Изменено в версии 3.10: Теперь она возвращает NULL, если вызвана до Py_Initialize().

void Py_SetPath(const wchar_t*)
Part of the Stable ABI since version 3.7.

Установка пути поиска модуля по умолчанию. Если эта функция вызвана до Py_Initialize(), то Py_GetPath() не будет пытаться вычислить путь поиска по умолчанию, а будет использовать предоставленный путь. Это полезно, если Python встраивается в приложение, которое полностью знает расположение всех модулей. Компоненты пути должны быть разделены разделительным символом, зависящим от платформы, который в Unix и macOS равен ':', в Windows - ';'.

Это также приводит к тому, что sys.executable устанавливается на полный путь программы (см. Py_GetProgramFullPath()), а sys.prefix и sys.exec_prefix становятся пустыми. После вызова Py_Initialize() вызывающая сторона должна изменить их, если это необходимо.

Используйте Py_DecodeLocale() для декодирования байтовой строки, чтобы получить строку wchar_*.

Аргумент path копируется внутри программы, поэтому вызывающая сторона может освободить его после завершения вызова.

Изменено в версии 3.8: Полный путь программы теперь используется для sys.executable вместо имени программы.

const char *Py_GetVersion()
Part of the Stable ABI.

Возвращает версию данного интерпретатора Python. Это строка, которая выглядит примерно так

"3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]"

Первое слово (до первого символа пробела) - это текущая версия Python; первые символы - это мажорная и минорная версии, разделенные точкой. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как sys.version.

const char *Py_GetPlatform()
Part of the Stable ABI.

Возвращает идентификатор платформы для текущей платформы. В Unix он формируется из «официального» названия операционной системы, преобразованного в нижний регистр, за которым следует номер основной ревизии; например, для Solaris 2.x, который также известен как SunOS 5.x, значение 'sunos5'. Для macOS это 'darwin'. В Windows это значение равно 'win'. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как sys.platform.

const char *Py_GetCopyright()
Part of the Stable ABI.

Возвращает официальную строку авторского права для текущей версии Python, например

'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'

Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как sys.copyright.

const char *Py_GetCompiler()
Part of the Stable ABI.

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

"[GCC 2.7.2.2]"

Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как часть переменной sys.version.

const char *Py_GetBuildInfo()
Part of the Stable ABI.

Возвращает информацию о порядковом номере и дате и времени сборки текущего экземпляра интерпретатора Python, например

"#67, Aug  1 1997, 22:34:28"

Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как часть переменной sys.version.

void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
Part of the Stable ABI.

Установите sys.argv на основе argc и argv. Эти параметры аналогичны тем, которые передаются в функцию программы main() с той разницей, что первая запись должна ссылаться на файл сценария, который будет выполняться, а не на исполняемый файл, на котором размещен интерпретатор Python. Если нет сценария, который будет выполняться, первая запись в argv может быть пустой строкой. Если эта функция не инициализирует sys.argv, то фатальное состояние сигнализируется с помощью Py_FatalError().

Если updatepath равен нулю, это все, что делает функция. Если updatepath ненулевой, функция также изменяет sys.path в соответствии со следующим алгоритмом:

  • Если в argv[0] передано имя существующего скрипта, то к sys.path добавляется абсолютный путь к директории, в которой находится скрипт.

  • В противном случае (то есть, если argc равен 0 или argv[0] не указывает на существующее имя файла), к sys.path добавляется пустая строка, что равносильно добавлению текущего рабочего каталога (".").

Используйте Py_DecodeLocale() для декодирования байтовой строки, чтобы получить строку wchar_*.

Примечание

Рекомендуется, чтобы приложения, встраивающие интерпретатор Python для целей, отличных от выполнения одного сценария, передавали 0 в качестве updatepath, а при желании сами обновляли sys.path. См. CVE-2008-5983.

В версиях до 3.1.3 вы можете добиться того же эффекта, вручную вытолкнув первый элемент sys.path после вызова PySys_SetArgv(), например, используя:

PyRun_SimpleString("import sys; sys.path.pop(0)\n");

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

void PySys_SetArgv(int argc, wchar_t **argv)
Part of the Stable ABI.

Эта функция работает как PySys_SetArgvEx() с updatepath, установленным в 1, если только интерпретатор python не был запущен с помощью -I.

Используйте Py_DecodeLocale() для декодирования байтовой строки, чтобы получить строку wchar_*.

Изменено в версии 3.4: Значение updatepath зависит от -I.

void Py_SetPythonHome(const wchar_t *home)
Part of the Stable ABI.

Устанавливает «домашний» каталог по умолчанию, то есть расположение стандартных библиотек Python. Значение строки аргумента см. в PYTHONHOME.

Аргумент должен указывать на строку символов с нулевым окончанием в статическом хранилище, содержимое которого не будет меняться в течение всего времени выполнения программы. Никакой код в интерпретаторе Python не изменит содержимое этого хранилища.

Используйте Py_DecodeLocale() для декодирования байтовой строки, чтобы получить строку wchar_*.

w_char *Py_GetPythonHome()
Part of the Stable ABI.

Возвращает «дом» по умолчанию, то есть значение, установленное предыдущим вызовом Py_SetPythonHome(), или значение переменной окружения PYTHONHOME, если она установлена.

Эта функция не должна вызываться до Py_Initialize(), иначе она возвращает NULL.

Изменено в версии 3.10: Теперь она возвращает NULL, если вызвана до Py_Initialize().

Состояние потоков и блокировка глобального интерпретатора

Интерпретатор Python не является полностью потокобезопасным. Для поддержки многопоточных программ Python существует глобальная блокировка, называемая global interpreter lock или GIL, которая должна быть у текущего потока, прежде чем он сможет безопасно получить доступ к объектам Python. Без блокировки даже самые простые операции могут вызвать проблемы в многопоточной программе: например, когда два потока одновременно увеличивают количество ссылок на один и тот же объект, количество ссылок может быть увеличено только один раз вместо двух.

Поэтому существует правило, что только тот поток, который получил GIL, может работать с объектами Python или вызывать функции Python/C API. Чтобы эмулировать параллельность выполнения, интерпретатор регулярно пытается переключать потоки (см. sys.setswitchinterval()). Блокировка также снимается во время потенциально блокирующих операций ввода-вывода, таких как чтение или запись файла, чтобы другие потоки Python могли в это время работать.

Интерпретатор Python хранит некоторую информацию о потоках в структуре данных под названием PyThreadState. Существует также одна глобальная переменная, указывающая на текущую PyThreadState: ее можно получить с помощью PyThreadState_Get().

Освобождение GIL от кода расширения

Большинство кода расширения, манипулирующего GIL, имеет следующую простую структуру:

Save the thread state in a local variable.
Release the global interpreter lock.
... Do some blocking I/O operation ...
Reacquire the global interpreter lock.
Restore the thread state from the local variable.

Это настолько частое явление, что для его упрощения существует пара макросов:

Py_BEGIN_ALLOW_THREADS
... Do some blocking I/O operation ...
Py_END_ALLOW_THREADS

Макрос Py_BEGIN_ALLOW_THREADS открывает новый блок и объявляет скрытую локальную переменную; макрос Py_END_ALLOW_THREADS закрывает блок.

Блок выше расширяется до следующего кода:

PyThreadState *_save;

_save = PyEval_SaveThread();
... Do some blocking I/O operation ...
PyEval_RestoreThread(_save);

Вот как работают эти функции: глобальная блокировка интерпретатора используется для защиты указателя на текущее состояние потока. При освобождении блокировки и сохранении состояния потока указатель текущего состояния потока должен быть получен до освобождения блокировки (поскольку другой поток может немедленно получить блокировку и сохранить свое состояние потока в глобальной переменной). И наоборот, при приобретении блокировки и восстановлении состояния потока блокировка должна быть приобретена до сохранения указателя состояния потока.

Примечание

Вызов системных функций ввода-вывода является наиболее распространенным случаем использования освобождения GIL, но это также может быть полезно перед вызовом длительных вычислений, которые не требуют доступа к объектам Python, например, сжатия или криптографических функций, работающих с буферами памяти. Например, стандартные модули zlib и hashlib освобождают GIL при сжатии или хэшировании данных.

Потоки, созданные не на языке Python

Когда потоки создаются с помощью специальных API Python (например, модуля threading), состояние потока автоматически ассоциируется с ними, поэтому приведенный выше код корректен. Однако когда потоки создаются из языка C (например, с помощью сторонней библиотеки с собственным управлением потоками), они не хранят GIL, и для них не существует структуры состояния потока.

Если вам нужно вызвать код Python из этих потоков (часто это является частью API обратного вызова, предоставляемого вышеупомянутой сторонней библиотекой), вы должны сначала зарегистрировать эти потоки в интерпретаторе, создав структуру данных состояния потока, затем получить GIL и, наконец, сохранить указатель состояния потока, прежде чем вы сможете начать использовать API Python/C. Когда вы закончите, вы должны сбросить указатель состояния потока, освободить GIL и, наконец, освободить структуру данных состояния потока.

Функции PyGILState_Ensure() и PyGILState_Release() делают все вышеперечисленное автоматически. Типичная идиома для вызова в Python из потока C такова:

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

/* Perform Python actions here. */
result = CallSomeFunction();
/* evaluate result or handle exception */

/* Release the thread. No Python API allowed beyond this point. */
PyGILState_Release(gstate);

Обратите внимание, что функции PyGILState_* предполагают наличие только одного глобального интерпретатора (создаваемого автоматически с помощью Py_Initialize()). Python поддерживает создание дополнительных интерпретаторов (с помощью Py_NewInterpreter()), но смешивание нескольких интерпретаторов и API PyGILState_* не поддерживается.

Предостережения по поводу fork()

Еще одна важная вещь, которую следует отметить о потоках, это их поведение перед лицом вызова C fork(). В большинстве систем с fork(), после форка процесса будет существовать только тот поток, который выдал форк. Это имеет конкретное влияние как на то, как должны обрабатываться блокировки, так и на все хранимое состояние во времени выполнения CPython.

Тот факт, что остается только «текущий» поток, означает, что все блокировки, удерживаемые другими потоками, никогда не будут освобождены. Python решает эту проблему для os.fork(), приобретая внутренние блокировки, которые он использует до развилки, и освобождая их после. Кроме того, он сбрасывает все Блокировка объектов в дочернем потоке. При расширении или встраивании Python нет способа сообщить Python о дополнительных (непитоновских) блокировках, которые необходимо получить до или сбросить после развилки. Для этого необходимо использовать средства ОС, такие как pthread_atfork(). Кроме того, при расширении или встраивании Python вызов fork() напрямую, а не через os.fork() (и возврат или вызов в Python) может привести к тупику из-за того, что одна из внутренних блокировок Python удерживается потоком, который прекратил свое существование после развилки. PyOS_AfterFork_Child() пытается сбросить необходимые блокировки, но не всегда может это сделать.

Тот факт, что все другие потоки уходят, также означает, что состояние времени выполнения CPython должно быть очищено должным образом, что и делает os.fork(). Это означает финализацию всех других объектов PyThreadState, принадлежащих текущему интерпретатору, и всех других объектов PyInterpreterState. Из-за этого и особой природы «main» interpreter, fork() следует вызывать только в «главном» потоке интерпретатора, где изначально была инициализирована глобальная среда выполнения CPython. Единственное исключение - если exec() будет вызван сразу после него.

API высокого уровня

Это наиболее часто используемые типы и функции при написании кода расширения C или при встраивании интерпретатора Python:

type PyInterpreterState
Part of the Limited API (as an opaque struct).

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

Нити, принадлежащие разным интерпретаторам, изначально не имеют ничего общего, кроме состояния процесса, такого как доступная память, открытые дескрипторы файлов и тому подобное. Глобальная блокировка интерпретатора также является общей для всех потоков, независимо от того, к какому интерпретатору они принадлежат.

type PyThreadState
Part of the Limited API (as an opaque struct).

Эта структура данных представляет состояние одного потока. Единственным открытым членом данных является interp (PyInterpreterState*), который указывает на состояние интерпретатора этого потока.

void PyEval_InitThreads()
Part of the Stable ABI.

Устаревшая функция, которая ничего не делает.

В Python 3.6 и старше эта функция создавала GIL, если он не существовал.

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

Изменено в версии 3.7: Эта функция теперь вызывается Py_Initialize(), поэтому вам больше не нужно вызывать ее самостоятельно.

Изменено в версии 3.2: Эта функция больше не может быть вызвана перед Py_Initialize().

Deprecated since version 3.9, will be removed in version 3.11.

int PyEval_ThreadsInitialized()
Part of the Stable ABI.

Возвращает ненулевое значение, если была вызвана функция PyEval_InitThreads(). Эта функция может быть вызвана без удержания GIL, и поэтому может быть использована для избежания обращений к API блокировки при однопоточном выполнении.

Изменено в версии 3.7: Теперь GIL инициализируется Py_Initialize().

Deprecated since version 3.9, will be removed in version 3.11.

PyThreadState *PyEval_SaveThread()
Part of the Stable ABI.

Освободить глобальную блокировку интерпретатора (если она была создана) и сбросить состояние потока на NULL, возвращая предыдущее состояние потока (которое не является NULL). Если блокировка была создана, то текущий поток должен был ее получить.

void PyEval_RestoreThread(PyThreadState *tstate)
Part of the Stable ABI.

Приобрести глобальную блокировку интерпретатора (если она была создана) и установить состояние потока в tstate, которое не должно быть NULL. Если блокировка была создана, текущий поток не должен ее получить, иначе возникнет тупик.

Примечание

Вызов этой функции из потока в момент завершения работы интерпретатора приведет к завершению потока, даже если поток не был создан Python. Вы можете использовать _Py_IsFinalizing() или sys.is_finalizing(), чтобы проверить, находится ли интерпретатор в процессе завершения перед вызовом этой функции, чтобы избежать нежелательного завершения.

PyThreadState *PyThreadState_Get()
Part of the Stable ABI.

Возвращает текущее состояние потока. Глобальная блокировка интерпретатора должна быть удержана. Если текущее состояние потока равно NULL, то выдается фатальная ошибка (чтобы вызывающая сторона не проверяла наличие NULL).

PyThreadState *PyThreadState_Swap(PyThreadState *tstate)
Part of the Stable ABI.

Поменяйте текущее состояние потока на состояние потока, заданное аргументом tstate, который может быть NULL. Глобальная блокировка интерпретатора должна удерживаться и не снимается.

Следующие функции используют локальное хранение потоков и не совместимы с суб-интерпретаторами:

PyGILState_STATE PyGILState_Ensure()
Part of the Stable ABI.

Убедитесь, что текущий поток готов вызвать Python C API независимо от текущего состояния Python или глобальной блокировки интерпретатора. Эта функция может быть вызвана столько раз, сколько захочет поток, если каждый вызов сопровождается вызовом PyGILState_Release(). В общем случае, между вызовами PyGILState_Ensure() и PyGILState_Release() можно использовать другие API, связанные с потоком, при условии, что состояние потока будет восстановлено до состояния, предшествующего вызову Release(). Например, допустимо обычное использование макросов Py_BEGIN_ALLOW_THREADS и Py_END_ALLOW_THREADS.

Возвращаемое значение - это непрозрачный «хэндл» состояния потока, когда был вызван PyGILState_Ensure(), который должен быть передан в PyGILState_Release(), чтобы гарантировать, что Python останется в том же состоянии. Несмотря на то, что рекурсивные вызовы разрешены, эти дескрипторы не могут быть общими - каждый уникальный вызов PyGILState_Ensure() должен сохранить дескриптор для своего вызова PyGILState_Release().

Когда функция вернется, текущий поток будет владеть GIL и сможет вызывать произвольный код Python. Отказ является фатальной ошибкой.

Примечание

Вызов этой функции из потока в момент завершения работы интерпретатора приведет к завершению потока, даже если поток не был создан Python. Вы можете использовать _Py_IsFinalizing() или sys.is_finalizing(), чтобы проверить, находится ли интерпретатор в процессе завершения перед вызовом этой функции, чтобы избежать нежелательного завершения.

void PyGILState_Release(PyGILState_STATE)
Part of the Stable ABI.

Освободить все ранее полученные ресурсы. После этого вызова состояние Python будет таким же, каким оно было до соответствующего вызова PyGILState_Ensure() (но обычно это состояние неизвестно вызывающей стороне, поэтому используется API GILState).

Каждому вызову PyGILState_Ensure() должен соответствовать вызов PyGILState_Release() в том же потоке.

PyThreadState *PyGILState_GetThisThreadState()
Part of the Stable ABI.

Получить текущее состояние потока для данного потока. Может вернуть NULL, если для текущего потока не был использован API GILState. Обратите внимание, что главный поток всегда имеет такое состояние потока, даже если в главном потоке не был сделан вызов автосостояния потока. Это в основном вспомогательная/диагностическая функция.

int PyGILState_Check()

Возвращает 1, если текущий поток удерживает GIL, и 0 в противном случае. Эта функция может быть вызвана из любого потока в любое время. Только если у него было инициализировано состояние потока Python и в данный момент он удерживает GIL, он вернет 1. Это в основном вспомогательная/диагностическая функция. Она может быть полезна, например, в контекстах обратного вызова или функциях распределения памяти, когда знание того, что GIL заблокирован, может позволить вызывающей стороне выполнять чувствительные действия или вести себя по-другому.

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

Следующие макросы обычно используются без точки с запятой; пример использования можно найти в исходном дистрибутиве Python.

Py_BEGIN_ALLOW_THREADS
Part of the Stable ABI.

Этот макрос расширяется до { PyThreadState *_save; _save = PyEval_SaveThread();. Обратите внимание, что он содержит открывающую скобку; он должен быть сопоставлен со следующим макросом Py_END_ALLOW_THREADS. Дальнейшее обсуждение этого макроса см. выше.

Py_END_ALLOW_THREADS
Part of the Stable ABI.

Этот макрос расширяется до PyEval_RestoreThread(_save); }. Обратите внимание, что он содержит закрывающую скобку; он должен быть сопоставлен с более ранним макросом Py_BEGIN_ALLOW_THREADS. Дальнейшее обсуждение этого макроса см. выше.

Py_BLOCK_THREADS
Part of the Stable ABI.

Этот макрос расширяется до PyEval_RestoreThread(_save);: он эквивалентен Py_END_ALLOW_THREADS без закрывающей скобки.

Py_UNBLOCK_THREADS
Part of the Stable ABI.

Этот макрос расширяется до _save = PyEval_SaveThread();: он эквивалентен Py_BEGIN_ALLOW_THREADS без открывающей скобки и объявления переменной.

Низкоуровневый API

Все следующие функции должны быть вызваны после Py_Initialize().

Изменено в версии 3.7: Py_Initialize() теперь инициализирует GIL.

PyInterpreterState *PyInterpreterState_New()
Part of the Stable ABI.

Создайте новый объект состояния интерпретатора. Глобальная блокировка интерпретатора не обязательно должна удерживаться, но может быть удержана, если необходимо сериализовать вызовы этой функции.

Вызывает auditing event cpython.PyInterpreterState_New без аргументов.

void PyInterpreterState_Clear(PyInterpreterState *interp)
Part of the Stable ABI.

Сброс всей информации в объекте состояния интерпретатора. Глобальная блокировка интерпретатора должна быть сохранена.

Вызывает auditing event cpython.PyInterpreterState_Clear без аргументов.

void PyInterpreterState_Delete(PyInterpreterState *interp)
Part of the Stable ABI.

Уничтожить объект состояния интерпретатора. Глобальная блокировка интерпретатора не должна удерживаться. Состояние интерпретатора должно быть сброшено предыдущим вызовом PyInterpreterState_Clear().

PyThreadState *PyThreadState_New(PyInterpreterState *interp)
Part of the Stable ABI.

Создает новый объект состояния потока, принадлежащий данному объекту интерпретатора. Глобальная блокировка интерпретатора не обязательно должна удерживаться, но может быть удержана, если это необходимо для сериализации вызовов этой функции.

void PyThreadState_Clear(PyThreadState *tstate)
Part of the Stable ABI.

Сброс всей информации в объекте состояния потока. Глобальная блокировка интерпретатора должна быть удержана.

Изменено в версии 3.9: Эта функция теперь вызывает обратный вызов PyThreadState.on_delete. Ранее это происходило в PyThreadState_Delete().

void PyThreadState_Delete(PyThreadState *tstate)
Part of the Stable ABI.

Уничтожить объект состояния потока. Глобальная блокировка интерпретатора не должна удерживаться. Состояние потока должно быть сброшено предыдущим вызовом PyThreadState_Clear().

void PyThreadState_DeleteCurrent(void)

Уничтожить текущее состояние потока и снять глобальную блокировку интерпретатора. Как и в случае с PyThreadState_Delete(), глобальная блокировка интерпретатора не обязательно должна удерживаться. Состояние потока должно быть сброшено предыдущим вызовом PyThreadState_Clear().

PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate)
Part of the Stable ABI since version 3.10.

Получить текущий кадр состояния потока Python tstate.

Возвращает strong reference. Возвращает NULL, если в данный момент не выполняется ни один кадр.

См. также PyEval_GetFrame().

tstate не должно быть NULL.

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

uint64_t PyThreadState_GetID(PyThreadState *tstate)
Part of the Stable ABI since version 3.10.

Получите уникальный идентификатор состояния потока Python tstate.

tstate не должно быть NULL.

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

PyInterpreterState *PyThreadState_GetInterpreter(PyThreadState *tstate)
Part of the Stable ABI since version 3.10.

Получить интерпретатор состояния потока Python tstate.

tstate не должно быть NULL.

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

PyInterpreterState *PyInterpreterState_Get(void)
Part of the Stable ABI since version 3.9.

Получить текущий интерпретатор.

Выдает фатальную ошибку, если нет текущего состояния потока Python или нет текущего интерпретатора. Он не может возвращать NULL.

Вызывающий должен удерживать GIL.

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

int64_t PyInterpreterState_GetID(PyInterpreterState *interp)
Part of the Stable ABI since version 3.7.

Возвращает уникальный идентификатор интерпретатора. Если при этом была допущена ошибка, то возвращается -1 и устанавливается ошибка.

Вызывающий должен удерживать GIL.

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

PyObject *PyInterpreterState_GetDict(PyInterpreterState *interp)
Part of the Stable ABI since version 3.8.

Возвращает словарь, в котором могут храниться данные, специфичные для интерпретатора. Если эта функция возвращает NULL, то исключение не было вызвано, и вызывающая сторона должна считать, что диктант, специфичный для интерпретатора, недоступен.

Это не замена PyModule_GetState(), которую расширения должны использовать для хранения специфической для интерпретатора информации о состоянии.

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

typedef PyObject *(*_PyFrameEvalFunction)(PyThreadState *tstate, PyFrameObject *frame, int throwflag)

Тип функции оценки кадра.

Параметр throwflag используется методом throw() генераторов: если ненулевой, обрабатывает текущее исключение.

Изменено в версии 3.9: Теперь функция принимает параметр tstate.

_PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp)

Получить функцию оценки кадра.

См. PEP 523 «Добавление API оценки кадров в CPython».

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

void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame)

Установите функцию оценки кадра.

См. PEP 523 «Добавление API оценки кадров в CPython».

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

PyObject *PyThreadState_GetDict()
Return value: Borrowed reference. Part of the Stable ABI.

Возвращает словарь, в котором расширения могут хранить информацию о состоянии конкретного потока. Каждое расширение должно использовать уникальный ключ для хранения информации о состоянии в словаре. Эту функцию можно вызывать, если текущее состояние потока недоступно. Если эта функция возвращает NULL, то исключение не было вызвано, и вызывающий должен считать, что текущее состояние потока недоступно.

int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
Part of the Stable ABI.

Асинхронно вызвать исключение в потоке. Аргумент id - это идентификатор целевого потока; exc - это объект исключения, который должен быть поднят. Эта функция не крадет никаких ссылок на exc. Чтобы предотвратить наивное злоупотребление, вы должны написать собственное расширение C для вызова этой функции. Должна вызываться с установленным GIL. Возвращает количество измененных состояний потока; обычно это единица, но если идентификатор потока не найден, то будет ноль. Если exc равен NULL, то ожидающее исключение (если таковое имеется) для потока удаляется. Это не вызывает никаких исключений.

Изменено в версии 3.7: Тип параметра id изменился с long на unsigned long.

void PyEval_AcquireThread(PyThreadState *tstate)
Part of the Stable ABI.

Приобретите глобальную блокировку интерпретатора и установите текущее состояние потока в tstate, которое не должно быть NULL. Блокировка должна быть создана ранее. Если этот поток уже имеет блокировку, наступает тупик.

Примечание

Вызов этой функции из потока в момент завершения работы интерпретатора приведет к завершению потока, даже если поток не был создан Python. Вы можете использовать _Py_IsFinalizing() или sys.is_finalizing(), чтобы проверить, находится ли интерпретатор в процессе завершения перед вызовом этой функции, чтобы избежать нежелательного завершения.

Изменено в версии 3.8: Обновлено для соответствия PyEval_RestoreThread(), Py_END_ALLOW_THREADS() и PyGILState_Ensure(), и завершения текущего потока, если он вызывается во время завершения работы интерпретатора.

PyEval_RestoreThread() - это функция более высокого уровня, которая всегда доступна (даже когда потоки не инициализированы).

void PyEval_ReleaseThread(PyThreadState *tstate)
Part of the Stable ABI.

Сбросьте состояние текущего потока на NULL и освободите глобальную блокировку интерпретатора. Блокировка должна быть создана ранее и должна принадлежать текущему потоку. Аргумент tstate, который не должен быть NULL, используется только для проверки того, что он представляет текущее состояние потока - если это не так, будет сообщено о фатальной ошибке.

PyEval_SaveThread() - это функция более высокого уровня, которая всегда доступна (даже когда потоки не инициализированы).

void PyEval_AcquireLock()
Part of the Stable ABI.

Приобретите глобальную блокировку интерпретатора. Блокировка должна быть создана ранее. Если этот поток уже имеет блокировку, наступает тупик.

Не рекомендуется, начиная с версии 3.2: Эта функция не обновляет текущее состояние потока. Вместо нее используйте PyEval_RestoreThread() или PyEval_AcquireThread().

Примечание

Вызов этой функции из потока в момент завершения работы интерпретатора приведет к завершению потока, даже если поток не был создан Python. Вы можете использовать _Py_IsFinalizing() или sys.is_finalizing(), чтобы проверить, находится ли интерпретатор в процессе завершения перед вызовом этой функции, чтобы избежать нежелательного завершения.

Изменено в версии 3.8: Обновлено для соответствия PyEval_RestoreThread(), Py_END_ALLOW_THREADS() и PyGILState_Ensure(), и завершения текущего потока, если он вызывается во время завершения работы интерпретатора.

void PyEval_ReleaseLock()
Part of the Stable ABI.

Освободите глобальную блокировку интерпретатора. Блокировка должна быть создана ранее.

Не рекомендуется, начиная с версии 3.2: Эта функция не обновляет текущее состояние потока. Вместо нее используйте PyEval_SaveThread() или PyEval_ReleaseThread().

Поддержка суб-интерпретаторов

Хотя в большинстве случаев вы будете использовать только один интерпретатор Python, бывают случаи, когда вам необходимо создать несколько независимых интерпретаторов в одном процессе и, возможно, даже в одном потоке. Вложенные интерпретаторы позволяют это сделать.

Интерпретатор «main» создается первым при инициализации среды выполнения. Обычно он является единственным интерпретатором Python в процессе. В отличие от вложенных интерпретаторов, главный интерпретатор имеет уникальные глобальные для процесса обязанности, такие как обработка сигналов. Он также отвечает за выполнение во время инициализации среды выполнения и обычно является активным интерпретатором во время финализации среды выполнения. Функция PyInterpreterState_Main() возвращает указатель на его состояние.

Вы можете переключаться между суб-интерпретаторами с помощью функции PyThreadState_Swap(). Создавать и уничтожать их можно с помощью следующих функций:

PyThreadState *Py_NewInterpreter()
Part of the Stable ABI.

Создайте новый суб-интерпретатор. Это (почти) полностью отдельная среда для выполнения кода Python. В частности, новый интерпретатор имеет отдельные, независимые версии всех импортированных модулей, включая фундаментальные модули builtins, __main__ и sys. Таблица загруженных модулей (sys.modules) и путь поиска модулей (sys.path) также разделены. Новая среда не имеет переменной sys.argv. Она имеет новые стандартные объекты файлов потока ввода/вывода sys.stdin, sys.stdout и sys.stderr (однако они ссылаются на те же самые базовые дескрипторы файлов).

Возвращаемое значение указывает на первое состояние потока, созданное в новом суб-интерпретаторе. Это состояние потока создается в текущем состоянии потока. Обратите внимание, что никакого реального потока не создается; см. обсуждение состояний потока ниже. Если создание нового интерпретатора не удалось, возвращается NULL; исключение не устанавливается, поскольку состояние исключения хранится в текущем состоянии потока, а текущего состояния потока может и не быть. (Как и все другие функции Python/C API, глобальная блокировка интерпретатора должна быть сохранена до вызова этой функции и сохраняется при возврате; однако, в отличие от большинства других функций Python/C API, при входе не обязательно должно быть текущее состояние потока).

Модули расширения разделяются между (под)интерпретаторами следующим образом:

  • Для модулей, использующих многофазную инициализацию, например PyModule_FromDefAndSpec(), для каждого интерпретатора создается и инициализируется отдельный объект модуля. Между этими объектами модуля совместно используются только статические и глобальные переменные уровня C.

  • Для модулей, использующих однофазную инициализацию, например, PyModule_Create(), при первом импорте конкретного расширения оно инициализируется нормально, а (неглубокая) копия словаря его модуля сохраняется. Когда это же расширение импортируется другим (под)интерпретатором, новый модуль инициализируется и заполняется содержимым этой копии; функция расширения init не вызывается. Таким образом, объекты в словаре модуля оказываются общими для всех (суб-)интерпретаторов, что может привести к нежелательному поведению (см. Bugs and caveats ниже).

    Обратите внимание, что это отличается от того, что происходит, когда расширение импортируется после того, как интерпретатор был полностью переинициализирован вызовом Py_FinalizeEx() и Py_Initialize(); в этом случае функция расширения initmodule *вызывается снова. Как и в случае с многофазной инициализацией, это означает, что между этими модулями совместно используются только статические и глобальные переменные уровня C.

void Py_EndInterpreter(PyThreadState *tstate)
Part of the Stable ABI.

Уничтожить (под)интерпретатор, представленный заданным состоянием потока. Данное состояние потока должно быть текущим состоянием потока. См. обсуждение состояний потоков ниже. Когда вызов возвращается, текущее состояние потока равно NULL. Все состояния потоков, связанные с этим интерпретатором, уничтожаются. (Глобальная блокировка интерпретатора должна быть установлена до вызова этой функции и сохраняется после возврата). Py_FinalizeEx() уничтожит все подинтерпретаторы, которые не были явно уничтожены в этот момент.

Ошибки и предостережения

Поскольку суб-интерпретаторы (и основной интерпретатор) являются частью одного процесса, изоляция между ними не идеальна — например, используя низкоуровневые файловые операции типа os.close(), они могут (случайно или злонамеренно) влиять на открытые файлы друг друга. Из-за того, как расширения разделяются между (под-)интерпретаторами, некоторые расширения могут работать неправильно; это особенно вероятно при использовании однофазной инициализации или (статических) глобальных переменных. Возможна вставка объектов, созданных в одном суб-интерпретаторе, в пространство имен другого (суб-)интерпретатора; по возможности этого следует избегать.

Особое внимание следует уделять тому, чтобы избежать совместного использования определяемых пользователем функций, методов, экземпляров или классов между суб-интерпретаторами, поскольку операции импорта, выполняемые такими объектами, могут повлиять на словарь загруженных модулей неправильного (суб-)интерпретатора. Не менее важно избегать совместного использования объектов, из которых можно получить вышеперечисленное.

Также обратите внимание, что сочетание этой функциональности с API PyGILState_* является деликатным, поскольку эти API предполагают биекцию между состояниями потоков Python и потоками на уровне ОС, а это предположение нарушается наличием подынтерпретаторов. Настоятельно рекомендуется не переключать подынтерпретаторы между парой совпадающих вызовов PyGILState_Ensure() и PyGILState_Release(). Более того, расширения (такие как ctypes), использующие эти API для обеспечения вызова Python-кода из потоков, созданных не на Python, вероятно, будут нарушены при использовании подынтерпретаторов.

Асинхронные уведомления

Предусмотрен механизм для асинхронных уведомлений основного потока интерпретатора. Эти уведомления принимают форму указателя на функцию и аргумента указателя на пустоту.

int Py_AddPendingCall(int (*func)(void*), void *arg, )
Part of the Stable ABI.

Запланировать вызов функции из главного потока интерпретатора. При успехе возвращается 0 и func ставится в очередь на вызов в главном потоке. При неудаче возвращается -1 без установки какого-либо исключения.

После успешной постановки в очередь func будет в конечном счете вызван из основного потока интерпретатора с аргументом arg. Она будет вызвана асинхронно по отношению к обычно выполняющемуся коду Python, но при соблюдении обоих этих условий:

  • на границе bytecode;

  • с основным потоком, удерживающим global interpreter lock (поэтому func может использовать полный C API).

func должен возвращать 0 при успехе, или -1 при неудаче с установленным исключением. func не будет прерван для выполнения другого асинхронного уведомления рекурсивно, но он все еще может быть прерван для переключения потоков, если глобальная блокировка интерпретатора освобождена.

Для работы этой функции не требуется текущее состояние потока, и ей не нужна глобальная блокировка интерпретатора.

Чтобы вызвать эту функцию в подынтерпретаторе, вызывающая сторона должна владеть GIL. В противном случае функция func может быть запланирована для вызова из неправильного интерпретатора.

Предупреждение

Это низкоуровневая функция, полезная только в особых случаях. Нет никакой гарантии, что func будет вызвана как можно быстрее. Если основной поток занят выполнением системного вызова, func не будет вызвана до возвращения системного вызова. Эта функция в целом не подходит для вызова кода Python из произвольных потоков C. Вместо этого используйте PyGILState API.

Изменено в версии 3.9: Если эта функция вызывается в подынтерпретаторе, то функция func теперь планируется к вызову из подынтерпретатора, а не из основного интерпретатора. Каждый подынтерпретатор теперь имеет свой собственный список запланированных вызовов.

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

Профилирование и отслеживание

Интерпретатор Python предоставляет низкоуровневую поддержку для подключения средств профилирования и трассировки выполнения. Они используются для профилирования, отладки и инструментов анализа покрытия.

Этот C-интерфейс позволяет коду профилирования или трассировки избежать накладных расходов на обращение к вызываемым объектам на уровне Python, делая вместо этого прямой вызов функции C. Основные атрибуты объекта не изменились; интерфейс позволяет устанавливать функции трассировки на каждый поток, а основные события, сообщаемые функции трассировки, такие же, как сообщались функциям трассировки на уровне Python в предыдущих версиях.

typedef int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)

Тип функции трассировки, зарегистрированной с помощью PyEval_SetProfile() и PyEval_SetTrace(). Первым параметром является объект, переданный функции регистрации как obj, frame - объект кадра, к которому относится событие, what - одна из констант PyTrace_CALL, PyTrace_EXCEPTION, PyTrace_LINE, PyTrace_RETURN, PyTrace_C_CALL, PyTrace_C_EXCEPTION, PyTrace_C_RETURN или PyTrace_OPCODE, а arg зависит от значения what:

Значение что

Значение arg

PyTrace_CALL

Всегда Py_None.

PyTrace_EXCEPTION

Информация об исключении, возвращаемая командой sys.exc_info().

PyTrace_LINE

Всегда Py_None.

PyTrace_RETURN

Значение, возвращаемое вызывающей стороне, или NULL, если оно вызвано исключением.

PyTrace_C_CALL

Вызываемый объект функции.

PyTrace_C_EXCEPTION

Вызываемый объект функции.

PyTrace_C_RETURN

Вызываемый объект функции.

PyTrace_OPCODE

Всегда Py_None.

int PyTrace_CALL

Значение параметра what функции Py_tracefunc, когда сообщается о новом вызове функции или метода, или о новом входе в генератор. Обратите внимание, что создание итератора для функции-генератора не сообщается, поскольку в соответствующем кадре не происходит передачи управления байткоду Python.

int PyTrace_EXCEPTION

Значение параметра what функции Py_tracefunc, когда было вызвано исключение. Функция обратного вызова вызывается с этим значением для what после обработки любого байткода, после чего исключение становится установленным в выполняемом кадре. Эффект от этого заключается в том, что поскольку распространение исключения заставляет стек Python разматываться, обратный вызов вызывается при возврате в каждый фрейм по мере распространения исключения. Эти события получают только функции трассировки; профилировщику они не нужны.

int PyTrace_LINE

Значение, передаваемое в качестве параметра what функции Py_tracefunc (но не функции профилирования), когда сообщается о событии с номером строки. Оно может быть отключено для кадра путем установки f_trace_lines в 0 на этом кадре.

int PyTrace_RETURN

Значение для параметра what функции Py_tracefunc, когда вызов собирается вернуться.

int PyTrace_C_CALL

Значение для параметра what функции Py_tracefunc, когда собирается вызвать функцию C.

int PyTrace_C_EXCEPTION

Значение параметра what для функций Py_tracefunc, когда функция языка Си вызвала исключение.

int PyTrace_C_RETURN

Значение для параметра what функции Py_tracefunc, когда функция C вернулась.

int PyTrace_OPCODE

Значение параметра what для функций Py_tracefunc (но не профилирующих функций), когда новый опкод должен быть выполнен. Это событие не испускается по умолчанию: его нужно явно запросить, установив f_trace_opcodes в 1 на фрейме.

void PyEval_SetProfile(Py_tracefunc func, PyObject *obj)

Установите функцию профилировщика в func. Параметр obj передается функции в качестве первого параметра и может быть любым объектом Python или NULL. Если функция профиля должна сохранять состояние, использование разного значения obj для каждого потока обеспечивает удобное и потокобезопасное место для его хранения. Функция profile вызывается для всех отслеживаемых событий, кроме PyTrace_LINE PyTrace_OPCODE и PyTrace_EXCEPTION.

Вызывающий должен удерживать клавишу GIL.

void PyEval_SetTrace(Py_tracefunc func, PyObject *obj)

Установите функцию трассировки на func. Это аналогично PyEval_SetProfile(), за исключением того, что функция трассировки получает события, связанные с номерами строк и событиями, относящимися к каждому операционному коду, но не получает никаких событий, связанных с вызовом объектов функций языка Си. Любая функция трассировки, зарегистрированная с помощью PyEval_SetTrace(), не будет получать PyTrace_C_CALL, PyTrace_C_EXCEPTION или PyTrace_C_RETURN в качестве значения параметра what.

Вызывающий должен удерживать клавишу GIL.

Расширенная поддержка отладчика

Эти функции предназначены только для использования продвинутыми инструментами отладки.

PyInterpreterState *PyInterpreterState_Head()

Возвращает объект состояния интерпретатора, находящийся во главе списка всех таких объектов.

PyInterpreterState *PyInterpreterState_Main()

Возвращает объект состояния основного интерпретатора.

PyInterpreterState *PyInterpreterState_Next(PyInterpreterState *interp)

Возвращает следующий после interp объект состояния интерпретатора из списка всех таких объектов.

PyThreadState *PyInterpreterState_ThreadHead(PyInterpreterState *interp)

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

PyThreadState *PyThreadState_Next(PyThreadState *tstate)

Возвращает следующий после tstate объект состояния потока из списка всех таких объектов, принадлежащих одному объекту PyInterpreterState.

Поддержка локального хранения данных

Интерпретатор Python обеспечивает низкоуровневую поддержку потокового локального хранилища (TLS), которая оборачивает базовую реализацию TLS для поддержки API потокового локального хранилища на уровне Python (threading.local). API уровня CPython C аналогичны тем, которые предлагаются pthreads и Windows: использование ключа потока и функций для привязки значения void* к потоку.

GIL не нужно удерживать при вызове этих функций; они обеспечивают собственную блокировку.

Обратите внимание, что Python.h не включает объявление TLS APIs, вам необходимо включить pythread.h для использования потоково-локального хранения.

Примечание

Ни одна из этих функций API не управляет памятью от имени значений void*. Вы должны выделять и удалять их самостоятельно. Если значения void* окажутся PyObject*, эти функции также не будут выполнять операции refcount для них.

API Thread Specific Storage (TSS)

API TSS введен для замены использования существующего API TLS в интерпретаторе CPython. Этот API использует новый тип Py_tss_t вместо int для представления ключей потоков.

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

См.также

«Новый C-API для потоково-локального хранения в CPython» (PEP 539)

type Py_tss_t

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

Когда Py_LIMITED_API не определено, допускается статическое выделение этого типа по Py_tss_NEEDS_INIT.

Py_tss_NEEDS_INIT

Этот макрос расширяется до инициализатора для переменных Py_tss_t. Обратите внимание, что этот макрос не будет определен с помощью Py_LIMITED_API.

Динамическое распределение

Динамическое выделение Py_tss_t, необходимое в модулях расширения, построенных с помощью Py_LIMITED_API, где статическое выделение этого типа невозможно из-за непрозрачности его реализации во время сборки.

Py_tss_t *PyThread_tss_alloc()
Part of the Stable ABI since version 3.7.

Возвращает значение, которое находится в том же состоянии, что и значение, инициализированное с помощью Py_tss_NEEDS_INIT, или NULL в случае сбоя динамического распределения.

void PyThread_tss_free(Py_tss_t *key)
Part of the Stable ABI since version 3.7.

Освободить заданную key, выделенную PyThread_tss_alloc(), после первого вызова PyThread_tss_delete(), чтобы убедиться, что все связанные локали потоков были освобождены. Это не работает, если аргумент key равен NULL.

Примечание

Освобожденный ключ становится висячим указателем. Вы должны сбросить ключ на NULL.

Методы

Параметр key этих функций не должен быть NULL. Более того, поведение PyThread_tss_set() и PyThread_tss_get() неопределено, если данная Py_tss_t не была инициализирована PyThread_tss_create().

int PyThread_tss_is_created(Py_tss_t *key)
Part of the Stable ABI since version 3.7.

Возвращает ненулевое значение, если данный Py_tss_t был инициализирован PyThread_tss_create().

int PyThread_tss_create(Py_tss_t *key)
Part of the Stable ABI since version 3.7.

Возвращает нулевое значение при успешной инициализации ключа TSS. Поведение не определено, если значение, на которое указывает аргумент key, не инициализировано Py_tss_NEEDS_INIT. Эта функция может быть вызвана несколько раз для одного и того же ключа – вызов ее для уже инициализированного ключа является безотказным и немедленно возвращает успех.

void PyThread_tss_delete(Py_tss_t *key)
Part of the Stable ABI since version 3.7.

Уничтожить ключ TSS, чтобы забыть значения, связанные с ключом, во всех потоках и изменить состояние инициализации ключа на uninitialized. Уничтоженный ключ может быть инициализирован снова с помощью PyThread_tss_create(). Эта функция может быть вызвана несколько раз для одного и того же ключа - вызов ее для уже уничтоженного ключа не имеет смысла.

int PyThread_tss_set(Py_tss_t *key, void *value)
Part of the Stable ABI since version 3.7.

Возвращает нулевое значение, указывающее на успешное связывание значения void* с ключом TSS в текущем потоке. Каждый поток имеет отдельное отображение ключа на значение void*.

void *PyThread_tss_get(Py_tss_t *key)
Part of the Stable ABI since version 3.7.

Возвращает значение void*, связанное с ключом TSS в текущем потоке. Возвращается NULL, если с ключом в текущем потоке не связано ни одно значение.

API Thread Local Storage (TLS)

Не рекомендуется, начиная с версии 3.7: Этот API заменен на Thread Specific Storage (TSS) API.

Примечание

Эта версия API не поддерживает платформы, на которых родной ключ TLS определен таким образом, что его нельзя безопасно привести к int. На таких платформах PyThread_create_key() будет немедленно возвращаться со статусом отказа, а все остальные функции TLS на таких платформах не работают.

Из-за проблемы совместимости, отмеченной выше, эта версия API не должна использоваться в новом коде.

int PyThread_create_key()
Part of the Stable ABI.
void PyThread_delete_key(int key)
Part of the Stable ABI.
int PyThread_set_key_value(int key, void *value)
Part of the Stable ABI.
void *PyThread_get_key_value(int key)
Part of the Stable ABI.
void PyThread_delete_key_value(int key)
Part of the Stable ABI.
void PyThread_ReInitTLS()
Part of the Stable ABI.
Вернуться на верх