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

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

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

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

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

Примечание

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

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

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

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

int Py_BytesWarningFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.bytes_warning, см. Python Initialization Configuration.

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

Устанавливается с помощью параметра -b.

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_DebugFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.parser_debug, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_DontWriteBytecodeFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.write_bytecode, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_FrozenFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.pathconfig_warnings, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_HashRandomizationFlag

Этот API оставлен для обратной совместимости: вместо него следует использовать настройки PyConfig.hash_seed и PyConfig.use_hash_seed, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_IgnoreEnvironmentFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.use_environment, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_InspectFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.inspect, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_InteractiveFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.interactive, см. Python Initialization Configuration.

Устанавливается с помощью параметра -i.

Не рекомендуется, начиная с версии 3.12.

int Py_IsolatedFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.isolated, см. Python Initialization Configuration.

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

Устанавливается с помощью параметра -I.

Added in version 3.4.

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_LegacyWindowsFSEncodingFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyPreConfig.legacy_windows_fs_encoding, см. Python Initialization Configuration.

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

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

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

Availability: Windows.

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_LegacyWindowsStdioFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.legacy_windows_stdio, см. Python Initialization Configuration.

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

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

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

Availability: Windows.

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_NoSiteFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.site_import, см. Python Initialization Configuration.

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

Устанавливается с помощью параметра -S.

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_NoUserSiteDirectory

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.user_site_directory, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_OptimizeFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.optimization_level, см. Python Initialization Configuration.

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_QuietFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.quiet, см. Python Initialization Configuration.

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

Устанавливается с помощью параметра -q.

Added in version 3.2.

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_UnbufferedStdioFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.buffered_stdio, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

int Py_VerboseFlag

Этот API сохранен для обратной совместимости: вместо него следует использовать настройку PyConfig.verbose, см. Python Initialization Configuration.

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

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

Утратил актуальность с версии 3.12, удален в версии 3.14.

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

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

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

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

Используйте функцию Py_InitializeFromConfig(), чтобы настроить Python Initialization Configuration.

Примечание

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

void Py_InitializeEx(int initsigs)
Часть Стабильный ABI.

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

Используйте функцию Py_InitializeFromConfig(), чтобы настроить Python Initialization Configuration.

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

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

int Py_IsFinalizing()
Часть Стабильный ABI с версии 3.13.

Возвращает true (ненулевое значение), если основным интерпретатором Python является shutting down. В противном случае возвращается false (ноль).

Added in version 3.13.

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, перед выходом из приложения.

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

Поднимает auditing event cpython._PySys_ClearAuditHooks без аргументов.

Added in version 3.6.

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

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

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

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

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

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

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

Не рекомендуется, начиная с версии 3.11.

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

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

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

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Вместо этого получите sys.executable.

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

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

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

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Вместо этого получите sys.prefix.

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

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

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

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

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

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

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Вместо этого получите sys.exec_prefix.

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

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

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

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Вместо этого получите sys.executable.

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

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

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

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Вместо этого получите sys.path.

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 Initialization Configuration.

Установите 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 Initialization Configuration.

Примечание

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

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

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

Added in version 3.1.3.

Не рекомендуется, начиная с версии 3.11.

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

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

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

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

См. также PyConfig.orig_argv и PyConfig.argv членов Python Initialization Configuration.

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

Не рекомендуется, начиная с версии 3.11.

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

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

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

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

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

Не рекомендуется, начиная с версии 3.11.

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

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

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

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Вместо этого получите переменную окружения PyConfig.home или PYTHONHOME.

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

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

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

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

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

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

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

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

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

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

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

PyThreadState *_save;

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

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

Примечание

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

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

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

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

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

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

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

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

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

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

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

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

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

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

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

type PyInterpreterState
Часть Ограниченный API (в виде непрозрачной структуры).

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

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

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.

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_GetUnchecked().

PyThreadState *PyThreadState_GetUnchecked()

Аналогично PyThreadState_Get(), но не убивает процесс с фатальной ошибкой, если результат равен NULL. Вызывающая сторона сама проверяет, является ли результат NULL.

Added in version 3.13: В Python 3.5 - 3.12 эта функция была частной и называлась _PyThreadState_UncheckedGet().

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

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

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

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

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

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

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

Примечание

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

void PyGILState_Release(PyGILState_STATE)
Часть Стабильный 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 заблокирован, может позволить вызывающей стороне выполнить чувствительные действия или вести себя иначе.

Added in version 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.

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

Поднимает auditing event cpython.PyInterpreterState_New без аргументов.

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

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

Поднимает auditing event 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.

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

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

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

Added in version 3.9.

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

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

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

Added in version 3.9.

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

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

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

Added in version 3.9.

void PyThreadState_EnterTracing(PyThreadState *tstate)

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

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

Added in version 3.11.

void PyThreadState_LeaveTracing(PyThreadState *tstate)

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

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

Added in version 3.11.

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

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

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

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

Added in version 3.9.

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

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

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

Added in version 3.7.

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

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

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

Added in version 3.8.

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

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

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

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

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

_PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp)

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

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

Added in version 3.9.

void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame)

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

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

Added in version 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.

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() - это функция более высокого уровня, которая всегда доступна (даже если потоки не были инициализированы).

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

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

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

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

type PyInterpreterConfig

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

Added in version 3.12.

Поля структуры:

int use_main_obmalloc

Если это значение равно 0, то подинтерпретатор будет использовать собственное состояние «объектного» аллокатора. В противном случае он будет использовать (разделять) состояние основного интерпретатора.

Если это 0, то check_multi_interp_extensions должно быть 1 (ненулевым). Если это 1, то gil не должно быть PyInterpreterConfig_OWN_GIL.

int allow_fork

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

Обратите внимание, что модуль subprocess по-прежнему работает, когда форк запрещен.

int allow_exec

Если это значение 0, то среда выполнения не будет поддерживать замену текущего процесса через exec (например, os.execv()) в любом потоке, где в данный момент активен суб-интерпретатор. В противном случае exec не имеет ограничений.

Обратите внимание, что модуль subprocess по-прежнему работает, когда exec запрещен.

int allow_threads

Если это значение равно 0, то модуль threading суб-интерпретатора не будет создавать потоки. В противном случае потоки разрешены.

int allow_daemon_threads

Если это значение равно 0, то модуль threading суб-интерпретатора не будет создавать потоки демонов. В противном случае создание демонских потоков разрешено (если allow_threads ненулевое).

int check_multi_interp_extensions

Если это значение равно 0, то все модули расширения могут быть импортированы, включая унаследованные (однофазный init) модули, в любом потоке, где в данный момент активен суб-интерпретатор. В противном случае можно импортировать только многофазные модули расширения init (см. PEP 489). (Также см. Py_mod_multiple_interpreters).

Это должно быть 1 (ненулевое значение), если use_main_obmalloc равно 0.

int gil

Это определяет работу GIL для суб-интерпретатора. Это может быть одно из следующих значений:

PyInterpreterConfig_DEFAULT_GIL

Используйте выбор по умолчанию (PyInterpreterConfig_SHARED_GIL).

PyInterpreterConfig_SHARED_GIL

Используйте (разделяйте) GIL основного интерпретатора.

PyInterpreterConfig_OWN_GIL

Используйте собственный GIL суб-интерпретатора.

Если это PyInterpreterConfig_OWN_GIL, то PyInterpreterConfig.use_main_obmalloc должно быть 0.

PyStatus Py_NewInterpreterFromConfig(PyThreadState **tstate_p, const PyInterpreterConfig *config)

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

Заданная config управляет параметрами, с которыми инициализируется интерпретатор.

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

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

Added in version 3.12.

Субинтерпретаторы наиболее эффективны, когда они изолированы друг от друга, а их функциональность ограничена:

PyInterpreterConfig config = {
    .use_main_obmalloc = 0,
    .allow_fork = 0,
    .allow_exec = 0,
    .allow_threads = 1,
    .allow_daemon_threads = 0,
    .check_multi_interp_extensions = 1,
    .gil = PyInterpreterConfig_OWN_GIL,
};
PyThreadState *tstate = Py_NewInterpreterFromConfig(&config);

Обратите внимание, что конфиг используется лишь кратковременно и не изменяется. При инициализации значения конфига преобразуются в различные значения PyInterpreterState. Копия конфига, доступная только для чтения, может храниться внутри PyInterpreterState.

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

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

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

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

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

Создайте новый суб-интерпретатор. По сути, это просто обертка вокруг Py_NewInterpreterFromConfig() с конфигурацией, сохраняющей существующее поведение. В результате получается неизолированный подинтерпретатор, который разделяет GIL основного интерпретатора, разрешает fork/exec, разрешает потоки демонов и разрешает однофазные модули init.

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

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

Py_FinalizeEx() уничтожит все подинтерпретаторы, которые не были явно уничтожены в этот момент.

GIL для каждого переводчика

Используя Py_NewInterpreterFromConfig(), вы можете создать подинтерпретатор, полностью изолированный от других интерпретаторов, в том числе имеющий свой собственный GIL. Самое важное преимущество такой изоляции заключается в том, что такой интерпретатор может выполнять код Python, не будучи заблокированным другими интерпретаторами и не блокируя других. Таким образом, один процесс Python может действительно использовать преимущества нескольких ядер процессора при выполнении кода Python. Изоляция также поощряет иной подход к параллелизму, чем просто использование потоков. (См. PEP 554).

Использование изолированного интерпретатора требует бдительности в сохранении этой изоляции. В частности, это означает, что нельзя делиться какими-либо объектами или изменяемым состоянием без гарантий потокобезопасности. Даже объекты, которые в остальном неизменяемы (например, None, (1, 5)), обычно не могут быть общими из-за refcount. Один из простых, но менее эффективных подходов к решению этой проблемы - использование глобальной блокировки на все использование некоторого состояния (или объекта). Как вариант, эффективно неизменяемые объекты (например, целые числа или строки) можно сделать безопасными, несмотря на их refcount, сделав их immortal. Фактически, это было сделано для встроенных синглтонов, небольших целых чисел и ряда других встроенных объектов.

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

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

Added in version 3.12.

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

Поскольку суб-интерпретаторы (и основной интерпретатор) являются частью одного процесса, изоляция между ними не идеальна - например, при использовании низкоуровневых файловых операций типа 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, но с соблюдением обоих условий:

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

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

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

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

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

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

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

Added in version 3.1.

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

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

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

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

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

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

Значение что

Значение слова arg

PyTrace_CALL

Всегда Py_None.

PyTrace_EXCEPTION

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

PyTrace_LINE

Всегда Py_None.

PyTrace_RETURN

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

PyTrace_C_CALL

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

PyTrace_C_EXCEPTION

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

PyTrace_C_RETURN

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

PyTrace_OPCODE

Всегда Py_None.

int PyTrace_CALL

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

int PyTrace_EXCEPTION

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

int PyTrace_LINE

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

int PyTrace_RETURN

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

int PyTrace_C_CALL

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

int PyTrace_C_EXCEPTION

Значение параметра what для функций Py_tracefunc, когда функция 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_SetProfileAllThreads(Py_tracefunc func, PyObject *obj)

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

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

Как и PyEval_SetProfile(), эта функция игнорирует любые исключения, возникающие при установке функций профиля во всех потоках.

Added in version 3.12.

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.

void PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *obj)

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

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

Как и PyEval_SetTrace(), эта функция игнорирует любые исключения, возникающие при установке функций трассировки во всех потоках.

Added in version 3.12.

Отслеживание ссылок

Added in version 3.13.

typedef int (*PyRefTracer)(PyObject*, int event, void *data)

Тип функции трассировки, зарегистрированной с помощью PyRefTracer_SetTracer(). Первый параметр - объект Python, который был только что создан (если event имеет значение PyRefTracer_CREATE) или скоро будет уничтожен (если event имеет значение PyRefTracer_DESTROY). Аргумент data - это непрозрачный указатель, который был предоставлен при вызове PyRefTracer_SetTracer().

Added in version 3.13.

int PyRefTracer_CREATE

Значение параметра event в PyRefTracer функции, когда был создан объект Python.

int PyRefTracer_DESTROY

Значение параметра event для функции PyRefTracer, когда объект Python был уничтожен.

int PyRefTracer_SetTracer(PyRefTracer tracer, void *data)

Зарегистрируйте функцию отслеживания ссылок. Функция будет вызываться при создании нового Python или при уничтожении объекта. Если указано data, то это должен быть непрозрачный указатель, который будет предоставлен при вызове функции трассировки. В случае успеха возвращается 0. Задайте исключение и верните -1 при ошибке.

Функции трассировщика не должны создавать внутри себя объекты Python, иначе вызов будет реентерабельным. Трассировщик также не должен очищать существующее исключение или устанавливать исключение. GIL будет удерживаться каждый раз при вызове функции трассировки.

При вызове этой функции необходимо удерживать GIL.

Added in version 3.13.

PyRefTracer PyRefTracer_GetTracer(void **data)

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

При вызове этой функции необходимо удерживать GIL.

Added in version 3.13.

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

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

PyInterpreterState *PyInterpreterState_Head()

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

PyInterpreterState *PyInterpreterState_Main()

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

PyInterpreterState *PyInterpreterState_Next(PyInterpreterState *interp)

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

PyThreadState *PyInterpreterState_ThreadHead(PyInterpreterState *interp)

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

PyThreadState *PyThreadState_Next(PyThreadState *tstate)

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

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

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

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

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

Примечание

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

API Thread Specific Storage (TSS)

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

Added in version 3.7.

См.также

«A New C-API for Thread-Local Storage in 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, чтобы забыть значения, связанные с ним, во всех потоках и изменить состояние инициализации ключа на uninitialized. Уничтоженный ключ может быть инициализирован снова по 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 Thread Local Storage (TLS)

Не рекомендуется, начиная с версии 3.7: Этот API заменен на Thread Specific Storage (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.