Spec-Zone.ru › Python 3.10

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

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

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

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

Следующие функции можно безопасно вызывать до инициализации 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_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, для кодировки и обработчика ошибок файловой системы.

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

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

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

int Py_LegacyWindowsStdioFlag

Если флаг ненулевой, использует io.FileIO вместо 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.

int Py_VerboseFlag

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

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

END_OF_DOCUMENT_MARKER

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

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

Инициализирует интерпретатор Python. В приложениях, которые используют встроенный Python, эта функция должна вызываться перед использованием любых других функций Python/C API; см. Перед инициализацией 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)
Часть Стабильного API.

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

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

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

int Py_FinalizeEx()
Часть Стабильного API с версии 3.6.

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

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

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

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

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

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

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

END_OF_DOCUMENT_MARKER

Параметры, общие для процесса

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

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

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

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

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

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

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

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

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

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

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

wchar *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-префикс для установки зависимых от платформы файлов. Он выводится по ряду сложных правил из имени программы, заданного с помощью 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-префикс бессмысленны и устанавливаются в пустую строку. Обратите внимание, что скомпилированные файлы байткода 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.

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

Устанавливает 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)
Часть Стабильной ABI.

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

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

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

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

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

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

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

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

Возвращает значение «домашней» папки по умолчанию, то есть значение, установленное предыдущим вызовом 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(), после того, как процесс разделился (fork), существует только тот поток, который инициировал fork. Это оказывает прямое влияние на то, как должны обрабатываться блокировки и все сохраненные данные в runtime CPython.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Устаревшая начиная с версии 3.9, будет удалена в версии 3.11.

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

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

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

Устаревшая начиная с версии 3.9, будет удалена в версии 3.11.

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 C Python, независимо от текущего состояния 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 в противном случае. Эта функция может вызываться из любого потока в любое время. Только если состояние потока Python было инициализировано и в данный момент удерживает GIL, она вернёт 1. Это в основном вспомогательная/диагностическая функция. Она может быть полезна, например, в контекстах обратного вызова или функциях выделения памяти, когда знание того, что 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.

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, 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()
Возвращаемое значение: Удержанная ссылка. Часть Стабильной ABI.

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

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

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

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

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

Вызывающий должен удерживать 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.

Вызывающий должен удерживать 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.

END_OF_DOCUMENT_MARKER

Поддержка локального хранения для потоков

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

Флаг блокировки интерпретатора 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.

Освобождает заданный ключ, выделенный функцией 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.

Примечание

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

Из-за проблемы совместимости, описанной выше, эта версия 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.10/c-api/init.html

Spec-Zone.ru

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