Spec-Zone.ru › Python 3.11

Инициализация, завершение и потоки

См. также Конфигурация Python-инициализации.

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

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

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

  • Функции конфигурации:

    • PyImport_AppendInittab()
    • PyImport_ExtendInittab()
    • PyInitFrozenExtensions()
    • PyMem_SetAllocator()
    • PyMem_SetupDebugHooks()
    • PyObject_SetArenaAllocator()
    • Py_SetPath()
    • Py_SetProgramName()
    • Py_SetPythonHome()
    • Py_SetStandardStreamEncoding()
    • PySys_AddWarnOption()
    • PySys_AddXOption()
    • PySys_ResetWarnOptions()
  • Информационные функции:

    • Py_IsInitialized()
    • PyMem_GetAllocator()
    • PyObject_GetArenaAllocator()
    • Py_GetBuildInfo()
    • Py_GetCompiler()
    • Py_GetCopyright()
    • Py_GetPlatform()
    • Py_GetVersion()
  • Утилиты:

    • Py_DecodeLocale()
  • Менеджеры памяти:

    • PyMem_RawMalloc()
    • PyMem_RawRealloc()
    • PyMem_RawCalloc()
    • PyMem_RawFree()

Примечание

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

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

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

Если флаг установлен опцией, значение флага равно количеству раз, когда эта опция была установлена. Например, -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_module и 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, для кодировки и обработчика ошибок файловой системы.

Устанавливается в 1 , если переменная среды PYTHONLEGACYWINDOWSFSENCODING имеет ненулевое значение.

См. PEP 529 для получения более подробной информации.

Доступность: Windows.

int Py_LegacyWindowsStdioFlag

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

Устанавливается в 1 , если переменная среды PYTHONLEGACYWINDOWSSTDIO имеет ненулевое значение.

См. PEP 528 для получения более подробной информации.

Доступность: 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.

END_OF_DOCUMENT_MARKER
int Py_VerboseFlag

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

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

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

void Py_Initialize()
Часть Стабильной ABI.

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

Это инициализирует таблицу загруженных модулей (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)
Часть Стабильной ABI.

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

int Py_IsInitialized()
Часть Стабильной ABI.

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

int Py_FinalizeEx()
Часть Стабильной ABI с версии 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() более одного раза.

Вызывает событие аудита cpython._PySys_ClearAuditHooks без аргументов.

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

void Py_Finalize()
Часть Стабильной ABI.

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

END_OF_DOCUMENT_MARKER

Параметры, применяемые ко всему процессу

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

Этот API поддерживается для обратной совместимости: вместо него следует использовать установку PyConfig.stdio_encoding и PyConfig.stdio_errors, см. Настройка инициализации Python.

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

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

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

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

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

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

Введено в версии 3.4.

Устарело начиная с версии 3.11.

void Py_SetProgramName(const wchar_t *name)
Часть Стабильной ABI.

Этот API поддерживается для обратной совместимости: вместо него следует использовать установку PyConfig.program_name, см. Настройка инициализации Python.

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

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

Устарело начиная с версии 3.11.

wchar_t *Py_GetProgramName()
Часть Стабильной ABI.

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

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

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

wchar_t *Py_GetPrefix()
Часть Стабильной 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()
Часть Стабильной ABI.

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

Предыстория: exec-prefix отличается от префикса, когда файлы, зависящие от платформы (такие как исполняемые файлы и динамические библиотеки), устанавливаются в разных каталогах. В типичной установке файлы, зависящие от платформы, могут устанавливаться в поддерево /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()
Часть Стабильной ABI.

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

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

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

wchar_t *Py_GetPath()
Часть Стабильной ABI.

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

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

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

void Py_SetPath(const wchar_t*)
Часть Стабильной ABI с версии 3.7.

Этот API сохранён для обратной совместимости: вместо него следует использовать установку PyConfig.module_search_paths и PyConfig.module_search_paths_set, см. Настройка конфигурации инициализации Python.

Устанавливает путь поиска модулей по умолчанию. Если эта функция вызывается до 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, а не имя программы.

Устарело начиная с версии 3.11.

const char *Py_GetVersion()
Часть Стабильной ABI.

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

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

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

См. также константу Py_Version.

const char *Py_GetPlatform()
Часть Стабильной ABI.

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

const char *Py_GetCopyright()
Часть Стабильной ABI.

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

'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'

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

const char *Py_GetCompiler()
Часть Стабильной ABI.

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

"[GCC 2.7.2.2]"

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

const char *Py_GetBuildInfo()
Часть Стабильной ABI.

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

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

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

void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
Часть Стабильной ABI.

Этот API сохранён для обратной совместимости: вместо него следует использовать установку PyConfig.argv, PyConfig.parse_argv и PyConfig.safe_path, см. Конфигурация инициализации Python.

Устанавливает 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_*.

См. также члены PyConfig.orig_argv и PyConfig.argv конфигурации инициализации Python.

Примечание

Рекомендуется, чтобы приложения, встраивающие интерпретатор 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.

Устарело начиная с версии 3.11.

void PySys_SetArgv(int argc, wchar_t **argv)
Часть Стабильной ABI.

Этот API сохранён для обратной совместимости: вместо него следует использовать установку PyConfig.argv и PyConfig.parse_argv, см. Конфигурация инициализации Python.

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

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

См. также члены PyConfig.orig_argv и PyConfig.argv конфигурации инициализации Python.

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

Устарело начиная с версии 3.11.

void Py_SetPythonHome(const wchar_t *home)
Часть Стабильной ABI.

Этот API сохранён для обратной совместимости: вместо него следует использовать установку PyConfig.home, см. Конфигурация инициализации Python.

Устанавливает директорию по умолчанию “home”, то есть расположение стандартных библиотек Python. См. PYTHONHOME для значения строки аргумента.

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

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

Устарело начиная с версии 3.11.

wchar_t *Py_GetPythonHome()
Часть Стабильной ABI.

Возвращает значение по умолчанию “home”, установленное предыдущим вызовом Py_SetPythonHome(), или значение переменной среды PYTHONHOME, если она установлена.

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

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

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

Интерпретатор Python не полностью потокобезопасен. Для поддержки многопоточных программ Python существует глобальная блокировка, называемая глобальной блокировкой интерпретатора или 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 о дополнительных (не Python) блокировках, которые необходимо захватить до или сбросить после разветвления. Для достижения того же результата необходимо использовать такие средства операционной системы, как pthread_atfork(). Кроме того, при расширении или встраивании Python вызов fork() напрямую, а не через os.fork() (и возвращение в Python или вызов Python) может привести к тупиковой ситуации из-за того, что одна из внутренних блокировок Python удерживается потоком, который не существует после разветвления. PyOS_AfterFork_Child() пытается сбросить необходимые блокировки, но не всегда может это сделать.

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

Высокоуровневый API

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

type PyInterpreterState
Часть Ограниченного API (как неявная структура).

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

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

type PyThreadState
Часть Ограниченного API (как неявная структура).

Эта структура данных представляет состояние одного потока. Единственный публичный член данных:

PyInterpreterState *interp

Состояние интерпретатора данного потока.

void PyEval_InitThreads()
Часть Стабильной ABI.

Функция, устаревшая и не выполняющая никаких действий.

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

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

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

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

Устарело начиная с версии 3.9.

int PyEval_ThreadsInitialized()
Часть Стабильной ABI.

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

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

Устарело начиная с версии 3.9.

PyThreadState *PyEval_SaveThread()
Часть Стабильной ABI.

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

void PyEval_RestoreThread(PyThreadState *tstate)
Часть Стабильной ABI.

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

Примечание

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

PyThreadState *PyThreadState_Get()
Часть Стабильной ABI.

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

PyThreadState *PyThreadState_Swap(PyThreadState *tstate)
Часть Стабильной ABI.

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

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

PyGILState_STATE PyGILState_Ensure()
Часть Стабильной ABI.

Убедитесь, что текущий поток готов к вызову API Python C независимо от текущего состояния Python или глобальной блокировки интерпретатора. Этот метод можно вызывать столько раз, сколько требуется потоку, при условии, что каждый вызов сопровождается вызовом PyGILState_Release(). В общем случае, другие API, связанные с потоками, могут использоваться между вызовами PyGILState_Ensure() и PyGILState_Release(), пока состояние потока не будет восстановлено до его предыдущего состояния до вызова 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)
Часть Стабильной ABI.

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

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

PyThreadState *PyGILState_GetThisThreadState()
Часть Стабильной ABI.

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

int PyGILState_Check()

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

Введено в версии 3.4.

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

Py_BEGIN_ALLOW_THREADS
Часть Стабильного ABI.

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

Py_END_ALLOW_THREADS
Часть Стабильного ABI.

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

Py_BLOCK_THREADS
Часть Стабильного ABI.

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

Py_UNBLOCK_THREADS
Часть Стабильного ABI.

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

API низкого уровня

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

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

PyInterpreterState *PyInterpreterState_New()
Часть Стабильной ABI.

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

Вызывает событие аудита cpython.PyInterpreterState_New без аргументов.

void PyInterpreterState_Clear(PyInterpreterState *interp)
Часть Стабильной ABI.

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

Вызывает событие аудита cpython.PyInterpreterState_Clear без аргументов.

void PyInterpreterState_Delete(PyInterpreterState *interp)
Часть Стабильной ABI.

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

PyThreadState *PyThreadState_New(PyInterpreterState *interp)
Часть Стабильной ABI.

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

void PyThreadState_Clear(PyThreadState *tstate)
Часть Стабильной ABI.

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

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

void PyThreadState_Delete(PyThreadState *tstate)
Часть Стабильной ABI.

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

void PyThreadState_DeleteCurrent(void)

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

PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate)
Часть Стабильной ABI с версии 3.10.

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

Возвращает сильную ссылку. Возвращает NULL если в данный момент не выполняется никакой фрейм.

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

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

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

uint64_t PyThreadState_GetID(PyThreadState *tstate)
Часть Стабильной ABI с версии 3.10.

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

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

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

PyInterpreterState *PyThreadState_GetInterpreter(PyThreadState *tstate)
Часть Стабильной ABI с версии 3.10.

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

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

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

void PyThreadState_EnterTracing(PyThreadState *tstate)

Приостанавливает отслеживание и профилирование в состоянии потока Python tstate.

Возобновить их можно с помощью функции PyThreadState_LeaveTracing().

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

void PyThreadState_LeaveTracing(PyThreadState *tstate)

Возобновляет отслеживание и профилирование в состоянии потока Python tstate, приостановленное функцией PyThreadState_EnterTracing().

См. также функции PyEval_SetTrace() и PyEval_SetProfile().

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

PyInterpreterState *PyInterpreterState_Get(void)
Часть Стабильной ABI с версии 3.9.

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

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

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

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

int64_t PyInterpreterState_GetID(PyInterpreterState *interp)
Часть Стабильной ABI с версии 3.7.

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

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

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

PyObject *PyInterpreterState_GetDict(PyInterpreterState *interp)
Часть Стабильной ABI с версии 3.8.

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

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

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

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

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

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

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

Изменено в версии 3.11: Параметр frame изменился с PyFrameObject* на _PyInterpreterFrame*.

_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.

END_OF_DOCUMENT_MARKER
PyObject *PyThreadState_GetDict()
Значение возврата: Заимствованная ссылка. Часть Стабильного ABI.

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

int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
Часть Стабильного ABI.

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

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

void PyEval_AcquireThread(PyThreadState *tstate)
Часть Стабильного 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)
Часть Стабильного ABI.

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

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

void PyEval_AcquireLock()
Часть Стабильного 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()
Часть Стабильного ABI.

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

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

Поддержка дочерних интерпретаторов

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

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

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

PyThreadState *Py_NewInterpreter()
Часть Стабильной ABI.

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

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

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

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

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

void Py_EndInterpreter(PyThreadState *tstate)
Часть Стабильной ABI.

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

Проблемы и замечания

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

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

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

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

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

int Py_AddPendingCall(int (*func)(void*), void *arg)
Часть Стабильной ABI.

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

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

  • на границе байт-кода;
  • с главным потоком, удерживающим глобальную блокировку интерпретатора (func, таким образом, может использовать весь API C).

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

Эта функция не требует текущего состояния потока для выполнения и не требует глобальной блокировки интерпретатора.

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

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

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

Изменено в версии 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:

Значение 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 при возникновении исключения в C-функции.

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 для каждого потока обеспечивает удобное и безопасное место для его хранения. Функция профилирования вызывается для всех отслеживаемых событий, кроме PyTrace_LINE PyTrace_OPCODE и PyTrace_EXCEPTION.

См. также функцию sys.setprofile().

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

void PyEval_SetTrace(Py_tracefunc func, PyObject *obj)

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

См. также функцию sys.settrace().

Вызывающая сторона должна удерживать 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 не включает объявление API TLS; вам нужно включить pythread.h для использования локального хранения данных потоков.

Примечание

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

API локального хранения данных потоков (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()
Часть Стабильной ABI с версии 3.7.

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

void PyThread_tss_free(Py_tss_t *key)
Часть Стабильной ABI с версии 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)
Часть Стабильной ABI с версии 3.7.

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

int PyThread_tss_create(Py_tss_t *key)
Часть Стабильной ABI с версии 3.7.

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

void PyThread_tss_delete(Py_tss_t *key)
Часть Стабильной ABI с версии 3.7.

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

int PyThread_tss_set(Py_tss_t *key, void *value)
Часть Стабильной ABI с версии 3.7.

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

void *PyThread_tss_get(Py_tss_t *key)
Часть Стабильной ABI с версии 3.7.

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

API локального хранения данных потоков (TLS)

Устарело начиная с версии 3.7: Этот API заменён API хранения данных для конкретного потока (TSS).

Примечание

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

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

int PyThread_create_key()
Часть стабильной ABI.
void PyThread_delete_key(int key)
Часть стабильной ABI.
int PyThread_set_key_value(int key, void *value)
Часть стабильной ABI.
void *PyThread_get_key_value(int key)
Часть стабильной ABI.
void PyThread_delete_key_value(int key)
Часть стабильной ABI.
void PyThread_ReInitTLS()
Часть стабильной ABI.

© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/c-api/init.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API