Инициализация, завершение и потоки
См. также Конфигурация Python-инициализации.
Перед инициализацией Python
В приложении, подключающем Python, функция Py_Initialize() должна быть вызвана перед использованием любых других функций Python/C API; за исключением нескольких функций и глобальных переменных конфигурации.
Следующие функции можно безопасно вызывать до инициализации Python:
-
Функции конфигурации:
-
Информационные функции:
-
Утилиты:
-
Менеджеры памяти:
Примечание
Следующие функции не должны вызываться до Py_Initialize(): Py_EncodeLocale(), Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix(), Py_GetProgramFullPath(), Py_GetPythonHome(), Py_GetProgramName() и PyEval_InitThreads().
Переменные глобальной конфигурации
В Python есть переменные для глобальной конфигурации, позволяющие управлять различными функциями и опциями. По умолчанию эти флаги контролируются опциями командной строки.
Если флаг установлен опцией, значение флага равно количеству раз, когда эта опция была установлена. Например, -b устанавливает Py_BytesWarningFlag в 1, а -bb устанавливает Py_BytesWarningFlag в 2.
-
int Py_BytesWarningFlag -
Выводит предупреждение при сравнении
bytesилиbytearrayсstrилиbytesсint. Выводит ошибку, если значение больше или равно2.Устанавливается опцией
-b.
-
int Py_DebugFlag -
Включает вывод отладки синтаксического анализатора (только для экспертов, зависит от параметров компиляции).
Устанавливается опцией
-dи переменной средыPYTHONDEBUG.
-
int Py_DontWriteBytecodeFlag -
Если значение ненулевое, Python не будет пытаться записать файлы
.pycпри импорте исходных модулей.Устанавливается опцией
-Bи переменной средыPYTHONDONTWRITEBYTECODE.
-
int Py_FrozenFlag -
Подавляет сообщения об ошибках при вычислении пути поиска модулей в
Py_GetPath().Приватный флаг, используемый программами
_freeze_moduleиfrozenmain.
-
int Py_HashRandomizationFlag -
Устанавливается в
1, если переменная средыPYTHONHASHSEEDимеет ненулевое значение.Если флаг ненулевой, использует переменную среды
PYTHONHASHSEEDдля инициализации секредного семени хеширования.
-
int Py_IgnoreEnvironmentFlag -
Игнорирует все переменные среды
PYTHON*, например,PYTHONPATHиPYTHONHOME.
-
int Py_InspectFlag -
Если скрипт передан в качестве первого аргумента или используется опция
-c, переходит в интерактивный режим после выполнения скрипта или команды, даже еслиsys.stdinне является терминалом.Устанавливается опцией
-iи переменной средыPYTHONINSPECT.
-
int Py_InteractiveFlag -
Устанавливается опцией
-i.
-
int Py_IsolatedFlag -
Запускает Python в изолированном режиме. В изолированном режиме
sys.pathне содержит ни директорию скрипта, ни директорию site-packages пользователя.Устанавливается опцией
-I.Введено в версии 3.4.
-
int Py_LegacyWindowsFSEncodingFlag -
Если флаг ненулевой, использует кодировку
mbcsс обработчиком ошибокreplace, вместо кодировки UTF-8 с обработчиком ошибокsurrogatepass, для кодировки и обработчика ошибок файловой системы.Устанавливается в
1, если переменная средыPYTHONLEGACYWINDOWSFSENCODINGимеет ненулевое значение.См. PEP 529 для получения более подробной информации.
Доступность: Windows.
-
int Py_LegacyWindowsStdioFlag -
Если флаг ненулевой, использует
io.FileIOвместоio._WindowsConsoleIOдля стандартных потоковsys.Устанавливается в
1, если переменная средыPYTHONLEGACYWINDOWSSTDIOимеет ненулевое значение.См. PEP 528 для получения более подробной информации.
Доступность: Windows.
-
int Py_NoSiteFlag -
Отключает импорт модуля
siteи связанные с ним манипуляции сsys.path. Также отключает эти манипуляции, еслиsiteимпортируется позже (вызовитеsite.main(), если хотите, чтобы они были выполнены).Устанавливается опцией
-S.
-
int Py_NoUserSiteDirectory -
Не добавляет
user site-packages directoryвsys.path.Устанавливается опциями
-sи-I, а также переменной средыPYTHONNOUSERSITE.
-
int Py_OptimizeFlag -
Устанавливается опцией
-Oи переменной средыPYTHONOPTIMIZE.
-
int Py_QuietFlag -
Не отображает сообщения об авторских правах и версии, даже в интерактивном режиме.
Устанавливается опцией
-q.Введено в версии 3.2.
-
int Py_UnbufferedStdioFlag -
Принудительно делает потоки stdout и stderr небуферизованными.
Устанавливается опцией
-uи переменной средыPYTHONUNBUFFERED.
-
int Py_VerboseFlag -
Выводить сообщение каждый раз при инициализации модуля, показывая место (имя файла или встроенный модуль), откуда он загружается. Если значение равно или больше
2, выводить сообщение для каждого файла, проверяемого при поиске модуля. Также предоставляет информацию о очистке модулей при выходе.Устанавливается опцией
-vи переменной средыPYTHONVERBOSE.
Инициализация и завершение интерпретатора
-
void Py_Initialize() -
Часть Стабильной ABI.
Инициализировать интерпретатор Python. В приложении, встраивающем Python, это следует вызывать перед использованием других функций API Python/C; см. Перед инициализацией Python для нескольких исключений.
Это инициализирует таблицу загруженных модулей (
sys.modules), и создаёт базовые модулиbuiltins,__main__иsys. Также инициализирует путь поиска модулей (sys.path). Оно не устанавливаетsys.argv; используйтеPySys_SetArgvEx()для этого. Это пустая операция при вызове во второй раз (без вызоваPy_FinalizeEx()вначале). Значение возврата отсутствует; ошибка – если инициализация завершилась неудачно.Примечание
В Windows изменяет режим консоли с
O_TEXTнаO_BINARY, что также повлияет на использование консоли не-Python-кодом, использующим C Runtime.
-
void Py_InitializeEx(int initsigs) -
Часть Стабильной ABI.
Эта функция работает так же, как
Py_Initialize(), если initsigs равно1. Если initsigs равно0, пропускает регистрацию обработки сигналов, что может быть полезно при встраивании Python.
-
int Py_IsInitialized() -
Часть Стабильной ABI.
Возвращает true (ненулевое значение), если интерпретатор Python был инициализирован, false (нуль) – если нет. После вызова
Py_FinalizeEx(), возвращает false, до тех пор, пока не будет вызваноPy_Initialize()снова.
-
int Py_FinalizeEx() -
Часть Стабильной ABI с версии 3.6.
Отменить все инициализации, сделанные функцией
Py_Initialize()и последующим использованием функций Python/C API, и уничтожить все под-интерпретаторы (см.Py_NewInterpreter()ниже), которые были созданы и ещё не уничтожены с последнего вызоваPy_Initialize(). В идеале, это освобождает всю память, выделенную интерпретатором Python. Это пустая операция при вызове во второй раз (без повторного вызоваPy_Initialize()). Обычно возвращает0. Если во время завершения произошли ошибки (вывод буферизованных данных), возвращает-1.Эта функция предоставляется по нескольким причинам. Приложение, встраивающее интерпретатор, может перезапустить Python, не перезапуская само приложение. Приложение, загрузившее интерпретатор Python из динамически загружаемой библиотеки (или DLL), может освободить всю память, выделенную Python, перед разгрузкой DLL. При поиске утечек памяти в приложении разработчик может освободить всю память, выделенную Python, перед завершением приложения.
Ошибки и замечания: Уничтожение модулей и объектов в модулях выполняется в случайном порядке; это может привести к сбоям деструкторов (
__del__()методы), когда они зависят от других объектов (даже функций) или модулей. Динамически загруженные расширенные модули, загруженные Python, не разгружаются. Небольшие объёмы памяти, выделенные интерпретатором Python, могут не быть освобождены (если вы обнаружите утечку, сообщите об этом). Память, связанная с циклическими ссылками между объектами, не освобождается. Некоторая память, выделенная расширенными модулями, может не быть освобождена. Некоторые расширения могут работать неправильно, если их процедура инициализации вызывается более одного раза; это может произойти, если приложение вызываетPy_Initialize()иPy_FinalizeEx()более одного раза.Вызывает событие аудита
cpython._PySys_ClearAuditHooksбез аргументов.Добавлена в версии 3.6.
-
void Py_Finalize() -
Часть Стабильной ABI.
Это обратная совместимая версия
Py_FinalizeEx(), которая игнорирует возвращаемое значение.
Параметры, применяемые ко всему процессу
-
int Py_SetStandardStreamEncoding(const char *encoding, const char *errors) -
Этот API поддерживается для обратной совместимости: вместо него следует использовать установку
PyConfig.stdio_encodingиPyConfig.stdio_errors, см. Настройка инициализации Python.Эту функцию следует вызывать до
Py_Initialize(), если она вообще вызывается. Она определяет кодировку и обработку ошибок для стандартного ввода/вывода, с тем же значением, что и вstr.encode().Она переопределяет значения
PYTHONIOENCODING, и позволяет коду внедрения управлять кодировкой ввода/вывода, когда переменная среды не работает.encoding и/или errors могут быть
NULLдля использованияPYTHONIOENCODINGи/или значения по умолчанию (в зависимости от других настроек).Обратите внимание, что
sys.stderrвсегда использует обработчик ошибок «backslashreplace», независимо от этого (или любого другого) параметра.Если вызывается
Py_FinalizeEx(), эта функция должна быть вызвана снова, чтобы повлиять на последующие вызовыPy_Initialize().Возвращает
0при успешном выполнении, ненулевое значение при ошибке (например, при вызове после того, как интерпретатор уже был инициализирован).Введено в версии 3.4.
Устарело начиная с версии 3.11.
-
void Py_SetProgramName(const wchar_t *name) -
Часть Стабильной ABI.
Этот API поддерживается для обратной совместимости: вместо него следует использовать установку
PyConfig.program_name, см. Настройка инициализации Python.Эту функцию следует вызывать до первого вызова
Py_Initialize(), если она вообще вызывается. Она сообщает интерпретатору значение параметраargv[0]для функцииmain()программы (преобразованное в символы с расширенным набором). Это используется функциейPy_GetPath()и некоторыми другими функциями ниже для поиска библиотек Python во время выполнения относительно исполняемого файла интерпретатора. Значение по умолчанию —'python'. Параметр должен указывать на строку символов с расширенным набором, завершающуюся нулем, в статической памяти, содержимое которой не будет меняться в течение выполнения программы. Никакой код в интерпретаторе Python не будет изменять содержимое этого хранилища.Используйте
Py_DecodeLocale()для декодирования строки байтов, чтобы получить строку wchar_*.Устарело начиная с версии 3.11.
-
wchar_t *Py_GetProgramName() -
Часть Стабильной ABI.
Возвращает имя программы, установленное с помощью
Py_SetProgramName(), или значение по умолчанию. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение.Эта функция не должна вызываться до
Py_Initialize(), в противном случае она возвращаетNULL.Изменено в версии 3.10: Теперь возвращает
NULLпри вызове доPy_Initialize().
-
wchar_t *Py_GetPrefix() -
Часть Стабильной ABI.
Возвращает префикс для установленных платформенно-независимых файлов. Он выводится по ряду сложных правил из имени программы, установленного с помощью
Py_SetProgramName(), и некоторых переменных среды; например, если имя программы —'/usr/local/bin/python', префикс —'/usr/local'. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Это соответствует переменной prefix в главномMakefileи аргументу--prefixскрипта configure во время сборки. Значение доступно коду Python какsys.prefix. Оно полезно только на Unix. См. также следующую функцию.Эта функция не должна вызываться до
Py_Initialize(), в противном случае она возвращаетNULL.Изменено в версии 3.10: Теперь возвращает
NULLпри вызове доPy_Initialize().
-
wchar_t *Py_GetExecPrefix() -
Часть Стабильной ABI.
Возвращает exec-prefix для установленных файлов, зависящих от платформы. Он выводится по ряду сложных правил из имени программы, установленного с помощью
Py_SetProgramName(), и некоторых переменных среды; например, если имя программы —'/usr/local/bin/python', exec-prefix —'/usr/local'. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Это соответствует переменной exec_prefix в главномMakefileи аргументу--exec-prefixскрипта configure во время сборки. Значение доступно коду Python какsys.exec_prefix. Оно полезно только на Unix.Предыстория: exec-prefix отличается от префикса, когда файлы, зависящие от платформы (такие как исполняемые файлы и динамические библиотеки), устанавливаются в разных каталогах. В типичной установке файлы, зависящие от платформы, могут устанавливаться в поддерево
/usr/local/plat, а платформенно-независимые — в/usr/local.В общем случае платформа — это комбинация семейств аппаратного и программного обеспечения, например, машины Sparc, работающие под операционной системой Solaris 2.x, считаются одной платформой, но машины Intel, работающие под Solaris 2.x, — другой, и машины Intel, работающие под Linux, — еще одной. Разные основные версии одной и той же операционной системы обычно также образуют разные платформы. Не-Unix операционные системы — это другой случай; стратегии установки на этих системах настолько разные, что префикс и exec-prefix бессмысленны и устанавливаются в пустую строку. Обратите внимание, что скомпилированные файлы байткода Python платформенно-независимы (но не независимы от версии Python, с помощью которой они были скомпилированы!).
Администраторы систем знают, как настроить программы mount или automount для совместного использования
/usr/localмежду платформами, при этом/usr/local/platявляется разным файловым систем для каждой платформы.Эта функция не должна вызываться до
Py_Initialize(), в противном случае она возвращаетNULL.Изменено в версии 3.10: Теперь возвращает
NULLпри вызове доPy_Initialize().
-
wchar_t *Py_GetProgramFullPath() -
Часть Стабильной ABI.
Возвращает полное имя программы-интерпретатора Python; это вычисляется как побочный эффект получения стандартного пути поиска модулей из имени программы (установленного с помощью
Py_SetProgramName()выше). Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно коду Python какsys.executable.Эта функция не должна вызываться до
Py_Initialize(), в противном случае она возвращаетNULL.Изменено в версии 3.10: Теперь возвращает
NULLпри вызове доPy_Initialize().
-
wchar_t *Py_GetPath() -
Часть Стабильной ABI.
Возвращает путь поиска модулей по умолчанию; он вычисляется из имени программы (установленного функцией
Py_SetProgramName()выше) и некоторых переменных окружения. Возвращаемая строка состоит из ряда имён каталогов, разделённых символом разделителя, зависящим от платформы. Символ разделителя —':'на Unix и macOS,';'на Windows. Возвращаемая строка указывает на статическую область памяти; вызывающая функция не должна изменять её значение. Списокsys.pathинициализируется этим значением при запуске интерпретатора; он может (и обычно изменяется) позже для изменения пути поиска загружаемых модулей.Эта функция не должна вызываться до
Py_Initialize(), в противном случае она возвращаетNULL.Изменено в версии 3.10: Теперь возвращает
NULLесли вызывается доPy_Initialize().
-
void Py_SetPath(const wchar_t*) -
Часть Стабильной ABI с версии 3.7.
Этот API сохранён для обратной совместимости: вместо него следует использовать установку
PyConfig.module_search_pathsиPyConfig.module_search_paths_set, см. Настройка конфигурации инициализации Python.Устанавливает путь поиска модулей по умолчанию. Если эта функция вызывается до
Py_Initialize(), тоPy_GetPath()не пытается вычислить путь поиска по умолчанию, но использует предоставленный вместо этого. Это полезно, если Python встроен приложением, которое полностью знает расположение всех модулей. Компоненты пути должны быть разделены символом разделителя, зависящим от платформы, который равен':'на Unix и macOS, и';'на Windows.Это также приводит к установке
sys.executableв полный путь программы (см.Py_GetProgramFullPath()) и к тому, чтоsys.prefixиsys.exec_prefixстановятся пустыми. Вызывающая функция должна самостоятельно изменить эти значения при необходимости после вызоваPy_Initialize().Используйте
Py_DecodeLocale()для декодирования строки байтов, чтобы получить строку wchar_*.Аргумент path копируется внутри, поэтому вызывающая функция может его освободить после завершения вызова.
Изменено в версии 3.8: Полный путь к программе теперь используется для
sys.executable, а не имя программы.Устарело начиная с версии 3.11.
-
const char *Py_GetVersion() -
Часть Стабильной ABI.
Возвращает версию этой интерпретатора Python. Это строка, которая выглядит примерно так
"3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]"
Первое слово (до первого пробела) — текущая версия Python; первые символы — основная и второстепенная версии, разделённые точкой. Возвращаемая строка указывает на статическую область памяти; вызывающая функция не должна изменять её значение. Это значение доступно коду Python как
sys.version.См. также константу
Py_Version.
-
const char *Py_GetPlatform() -
Часть Стабильной ABI.
Возвращает идентификатор платформы для текущей платформы. В Unix это формируется из «официального» имени операционной системы, приведённого к нижнему регистру, за которым следует номер основной ревизии; например, для Solaris 2.x, который также известен как SunOS 5.x, значение равно
'sunos5'. На macOS это'darwin'. На Windows это'win'. Возвращаемая строка указывает на статическую область памяти; вызывающая функция не должна изменять её значение. Это значение доступно коду Python какsys.platform.
-
const char *Py_GetCopyright() -
Часть Стабильной ABI.
Возвращает официальную строку авторских прав для текущей версии Python, например
'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'Возвращаемая строка указывает на статическую область памяти; вызывающая функция не должна изменять её значение. Это значение доступно коду Python как
sys.copyright.
-
const char *Py_GetCompiler() -
Часть Стабильной ABI.
Возвращает указание на компилятор, используемый для построения текущей версии Python, в квадратных скобках, например:
"[GCC 2.7.2.2]"
Возвращаемая строка указывает на статическую область памяти; вызывающая функция не должна изменять её значение. Это значение доступно коду Python как часть переменной
sys.version.
-
const char *Py_GetBuildInfo() -
Часть Стабильной ABI.
Возвращает информацию о номере последовательности и дате и времени сборки текущей экземпляра интерпретатора Python, например
"#67, Aug 1 1997, 22:34:28"
Возвращаемая строка указывает на статическую область памяти; вызывающая функция не должна изменять её значение. Это значение доступно коду Python как часть переменной
sys.version.
-
void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) -
Часть Стабильной ABI.
Этот API сохранён для обратной совместимости: вместо него следует использовать установку
PyConfig.argv,PyConfig.parse_argvиPyConfig.safe_path, см. Конфигурация инициализации Python.Устанавливает
sys.argvна основе argc и argv. Эти параметры аналогичны тем, которые передаются функцииmain()программы, с той разницей, что первый элемент должен ссылаться на исполняемый скрипт, а не на исполняемый файл, содержащий интерпретатор Python. Если не требуется запускать скрипт, первый элемент в argv может быть пустой строкой. Если эта функция не может инициализироватьsys.argv, то вызывается фатальная ошибка с помощьюPy_FatalError().Если updatepath равно нулю, функция выполняет только эти действия. Если updatepath отлично от нуля, функция также изменяет
sys.pathсогласно следующему алгоритму:- Если имя существующего скрипта передаётся в
argv[0], абсолютный путь к директории, в которой находится скрипт, добавляется в началоsys.path. - В противном случае (то есть, если argc равен
0илиargv[0]не указывает на существующий файл), пустая строка добавляется в началоsys.path, что эквивалентно добавлению текущей рабочей директории (".").
Используйте
Py_DecodeLocale()для декодирования строки байтов в строку wchar_*.См. также члены
PyConfig.orig_argvиPyConfig.argvконфигурации инициализации Python.Примечание
Рекомендуется, чтобы приложения, встраивающие интерпретатор Python с целью выполнения только одного скрипта, передавали
0в качестве updatepath и самостоятельно обновлялиsys.path, если это необходимо. См. CVE-2008-5983.В версиях до 3.1.3 вы могли добиться того же эффекта, удалив вручную первый элемент
sys.pathпосле вызоваPySys_SetArgv(), например, с помощью:PyRun_SimpleString("import sys; sys.path.pop(0)\n");Введено в версии 3.1.3.
Устарело начиная с версии 3.11.
- Если имя существующего скрипта передаётся в
-
void PySys_SetArgv(int argc, wchar_t **argv) -
Часть Стабильной ABI.
Этот API сохранён для обратной совместимости: вместо него следует использовать установку
PyConfig.argvиPyConfig.parse_argv, см. Конфигурация инициализации Python.Эта функция работает как
PySys_SetArgvEx()с updatepath, установленным в1, если интерпретатор python не был запущен с-I.Используйте
Py_DecodeLocale()для декодирования строки байтов в строку wchar_*.См. также члены
PyConfig.orig_argvиPyConfig.argvконфигурации инициализации Python.Изменено в версии 3.4: Значение updatepath зависит от
-I.Устарело начиная с версии 3.11.
-
void Py_SetPythonHome(const wchar_t *home) -
Часть Стабильной ABI.
Этот API сохранён для обратной совместимости: вместо него следует использовать установку
PyConfig.home, см. Конфигурация инициализации Python.Устанавливает директорию по умолчанию “home”, то есть расположение стандартных библиотек Python. См.
PYTHONHOMEдля значения строки аргумента.Аргумент должен указывать на строку с завершающим нулём в статическом хранилище, содержимое которой не будет изменено в течение выполнения программы. Ни один код в интерпретаторе Python не изменит содержимое этого хранилища.
Используйте
Py_DecodeLocale()для декодирования строки байтов в строку wchar_*.Устарело начиная с версии 3.11.
-
wchar_t *Py_GetPythonHome() -
Часть Стабильной ABI.
Возвращает значение по умолчанию “home”, установленное предыдущим вызовом
Py_SetPythonHome(), или значение переменной средыPYTHONHOME, если она установлена.Эта функция не должна вызываться до
Py_Initialize(), в противном случае она возвращаетNULL.Изменено в версии 3.10: Теперь возвращает
NULLесли вызвана доPy_Initialize().
Состояние потоков и глобальная блокировка интерпретатора
Интерпретатор Python не полностью потокобезопасен. Для поддержки многопоточных программ Python существует глобальная блокировка, называемая глобальной блокировкой интерпретатора или GIL, которая должна быть захвачена текущим потоком перед безопасным доступом к объектам Python. Без блокировки даже простейшие операции могут вызвать проблемы в многопоточной программе: например, когда два потока одновременно увеличивают счетчик ссылок одного объекта, счетчик ссылок может быть увеличен только один раз вместо двух.
Поэтому существует правило, что только поток, который захватил GIL, может выполнять операции с объектами Python или вызывать функции Python/C API. Для эмуляции одновременного выполнения интерпретатор регулярно пытается переключать потоки (см. sys.setswitchinterval()). Блокировка также освобождается вокруг потенциально блокирующих операций ввода-вывода, таких как чтение или запись файла, чтобы другие потоки Python могли выполняться тем временем.
Интерпретатор Python хранит некоторые данные, специфичные для потока, внутри структуры данных, называемой PyThreadState. Также существует одна глобальная переменная, указывающая на текущее PyThreadState: её можно получить с помощью PyThreadState_Get().
Освобождение GIL из кода расширения
Большинство кодов расширений, работающих с GIL, имеют следующую простую структуру:
Save the thread state in a local variable. Release the global interpreter lock. ... Do some blocking I/O operation ... Reacquire the global interpreter lock. Restore the thread state from the local variable.
Это так распространено, что существуют пары макросов для его упрощения:
Py_BEGIN_ALLOW_THREADS ... Do some blocking I/O operation ... Py_END_ALLOW_THREADS
Макрос Py_BEGIN_ALLOW_THREADS открывает новый блок и объявляет скрытую локальную переменную; макрос Py_END_ALLOW_THREADS закрывает блок.
Вышеуказанный блок расширяется до следующего кода:
PyThreadState *_save; _save = PyEval_SaveThread(); ... Do some blocking I/O operation ... PyEval_RestoreThread(_save);
Вот как работают эти функции: глобальная блокировка интерпретатора используется для защиты указателя на текущее состояние потока. При освобождении блокировки и сохранении состояния потока указатель на текущее состояние потока должен быть получен до освобождения блокировки (поскольку другой поток может немедленно захватить блокировку и сохранить своё состояние потока в глобальной переменной). И наоборот, при захвате блокировки и восстановлении состояния потока блокировка должна быть захвачена перед сохранением указателя на состояние потока.
Примечание
Вызов функций системного ввода-вывода является наиболее распространённым случаем для освобождения GIL, но он также может быть полезен перед вызовом длительных вычислений, которые не нуждаются в доступе к объектам Python, таких как сжатие или криптографические функции, работающие с буферами памяти. Например, стандартные модули zlib и hashlib освобождают GIL при сжатии или хешировании данных.
Потоки, созданные не Python
Когда потоки создаются с использованием специальных API Python (например, модуля threading), к ним автоматически связывается состояние потока, и приведенный выше код, следовательно, корректен. Однако, когда потоки создаются из C (например, сторонней библиотекой со своей системой управления потоками), они не держат GIL, и нет структуры состояния потока для них.
Если вам нужно вызвать код Python из этих потоков (часто это будет частью API обратного вызова, предоставляемого указанной сторонней библиотекой), необходимо сначала зарегистрировать эти потоки в интерпретаторе, создав структуру данных состояния потока, затем захватить GIL и, наконец, сохранить указатель на их состояние потока, прежде чем можно будет начать использовать API Python/C. Когда вы закончите, вы должны сбросить указатель на состояние потока, освободить GIL и, наконец, освободить структуру данных состояния потока.
Функции PyGILState_Ensure() и PyGILState_Release() автоматически выполняют всё это. Типичный способ вызова Python из C-потока:
PyGILState_STATE gstate; gstate = PyGILState_Ensure(); /* Perform Python actions here. */ result = CallSomeFunction(); /* evaluate result or handle exception */ /* Release the thread. No Python API allowed beyond this point. */ PyGILState_Release(gstate);
Обратите внимание, что функции PyGILState_* предполагают, что существует только один глобальный интерпретатор (созданный автоматически Py_Initialize()). Python поддерживает создание дополнительных интерпретаторов (с помощью Py_NewInterpreter()), но смешивание нескольких интерпретаторов и API PyGILState_* не поддерживается.
Осторожность при fork()
Ещё одна важная вещь, которую следует учитывать в отношении потоков, — это их поведение при вызове C-функции fork(). На большинстве систем с fork(), после разветвления процесса существует только тот поток, который инициировал разветвление. Это оказывает непосредственное влияние на то, как должны обрабатываться блокировки, и на всё хранимое состояние в среде выполнения CPython.
Тот факт, что остаются только «текущие» потоки, означает, что любые блокировки, удерживаемые другими потоками, никогда не будут освобождены. Python решает эту проблему для os.fork(), захватывая используемые им внутренние блокировки перед разветвлением и освобождая их после. Кроме того, он сбрасывает все объекты блокировки в дочернем процессе. При расширении или встраивании Python нет способа сообщить Python о дополнительных (не Python) блокировках, которые необходимо захватить до или сбросить после разветвления. Для достижения того же результата необходимо использовать такие средства операционной системы, как pthread_atfork(). Кроме того, при расширении или встраивании Python вызов fork() напрямую, а не через os.fork() (и возвращение в Python или вызов Python) может привести к тупиковой ситуации из-за того, что одна из внутренних блокировок Python удерживается потоком, который не существует после разветвления. PyOS_AfterFork_Child() пытается сбросить необходимые блокировки, но не всегда может это сделать.
Тот факт, что все остальные потоки исчезают, также означает, что состояние среды выполнения CPython там должно быть должным образом очищено, что и делает os.fork(). Это означает завершение всех других объектов PyThreadState, принадлежащих текущему интерпретатору, и всех других объектов PyInterpreterState. Из-за этого и особенностей “главного” интерпретатора, fork() должен вызываться только в «главном» потоке этого интерпретатора, где первоначально была инициализирована глобальная среда выполнения CPython. Исключением является случай, если exec() будет вызван непосредственно после этого.
Высокоуровневый API
Это наиболее часто используемые типы и функции при написании кода расширения C или при интеграции интерпретатора Python:
-
type PyInterpreterState -
Часть Ограниченного API (как неявная структура).
Эта структура данных представляет состояние, разделяемое несколькими взаимодействующими потоками. Потоки, принадлежащие одному интерпретатору, делят управление модулями и некоторые другие внутренние элементы. В этой структуре нет публичных членов.
Потоки, принадлежащие разным интерпретаторам, изначально ничего не делят, кроме состояния процесса, такого как доступная память, открытые дескрипторы файлов и т. п. Блокировка глобального интерпретатора (GIL) также разделяется всеми потоками независимо от того, к какому интерпретатору они относятся.
-
type PyThreadState -
Часть Ограниченного API (как неявная структура).
Эта структура данных представляет состояние одного потока. Единственный публичный член данных:
-
PyInterpreterState *interp -
Состояние интерпретатора данного потока.
-
-
void PyEval_InitThreads() -
Часть Стабильной ABI.
Функция, устаревшая и не выполняющая никаких действий.
В Python 3.6 и более ранних версиях эта функция создавала GIL, если он не существовал.
Изменено в версии 3.9: Функция теперь ничего не делает.
Изменено в версии 3.7: Эта функция теперь вызывается
Py_Initialize(), поэтому вы больше не должны её вызывать самостоятельно.Изменено в версии 3.2: Эта функция больше не может вызываться до
Py_Initialize().Устарело начиная с версии 3.9.
-
int PyEval_ThreadsInitialized() -
Часть Стабильной ABI.
Возвращает ненулевое значение, если
PyEval_InitThreads()была вызвана. Эту функцию можно вызывать без удержания GIL, а значит её можно использовать, чтобы избежать вызовов API блокировки при выполнении однопоточных задач.Изменено в версии 3.7: GIL теперь инициализируется
Py_Initialize().Устарело начиная с версии 3.9.
-
PyThreadState *PyEval_SaveThread() -
Часть Стабильной ABI.
Освобождает блокировку глобального интерпретатора (если она была создана) и сбрасывает состояние потока в
NULL, возвращая предыдущее состояние потока (которое неNULL). Если блокировка была создана, текущий поток должен её владеть.
-
void PyEval_RestoreThread(PyThreadState *tstate) -
Часть Стабильной ABI.
Приобретает блокировку глобального интерпретатора (если она была создана) и устанавливает состояние потока в tstate, которое не должно быть
NULL. Если блокировка была создана, текущий поток не должен её владеть, иначе произойдёт тупик.Примечание
Вызов этой функции из потока во время завершения работы интерпретатора приведёт к завершению потока, даже если он не был создан Python. Вы можете использовать
_Py_IsFinalizing()илиsys.is_finalizing(), чтобы проверить, завершается ли интерпретатор, прежде чем вызывать эту функцию, чтобы избежать нежелательного завершения.
-
PyThreadState *PyThreadState_Get() -
Часть Стабильной ABI.
Возвращает текущее состояние потока. Блокировка глобального интерпретатора должна быть удержана. Когда текущее состояние потока равно
NULL, это вызывает ошибку (чтобы вызывающая сторона не проверялаNULL).
-
PyThreadState *PyThreadState_Swap(PyThreadState *tstate) -
Часть Стабильной ABI.
Меняет текущее состояние потока на состояние потока, заданное аргументом tstate, которое может быть
NULL. Блокировка глобального интерпретатора должна быть удержана и не освобождается.
Следующие функции используют локальное хранилище потоков и несовместимы с подинтерпретаторами:
-
PyGILState_STATE PyGILState_Ensure() -
Часть Стабильной ABI.
Убедитесь, что текущий поток готов к вызову API Python C независимо от текущего состояния Python или глобальной блокировки интерпретатора. Этот метод можно вызывать столько раз, сколько требуется потоку, при условии, что каждый вызов сопровождается вызовом
PyGILState_Release(). В общем случае, другие API, связанные с потоками, могут использоваться между вызовамиPyGILState_Ensure()иPyGILState_Release(), пока состояние потока не будет восстановлено до его предыдущего состояния до вызова Release(). Например, нормальное использование макросовPy_BEGIN_ALLOW_THREADSиPy_END_ALLOW_THREADSприемлемо.Возвращаемое значение — это неявная «ручка» состояния потока, когда вызывался
PyGILState_Ensure(), и она должна быть передана вPyGILState_Release(), чтобы убедиться, что Python останется в том же состоянии. Хотя рекурсивные вызовы разрешены, эти ручки не могут быть совместно использованы — каждый уникальный вызовPyGILState_Ensure()должен сохранить ручку для своего вызоваPyGILState_Release().По завершении функции текущий поток будет владеть GIL и сможет вызывать произвольный код Python. Ошибка — это фатальная ошибка.
Примечание
Вызов этой функции из потока во время завершения работы интерпретатора приведёт к завершению потока, даже если он не был создан Python. Вы можете использовать
_Py_IsFinalizing()илиsys.is_finalizing(), чтобы проверить, завершается ли интерпретатор, прежде чем вызывать эту функцию, чтобы избежать нежелательного завершения.
-
void PyGILState_Release(PyGILState_STATE) -
Часть Стабильной ABI.
Освобождает ранее полученные ресурсы. После этого вызова состояние Python будет таким же, как и до соответствующего вызова
PyGILState_Ensure()(но, как правило, это состояние будет неизвестно вызывающей стороне, поэтому используется API GILState).Каждый вызов
PyGILState_Ensure()должен сопровождаться вызовомPyGILState_Release()в том же потоке.
-
PyThreadState *PyGILState_GetThisThreadState() -
Часть Стабильной ABI.
Получает текущее состояние потока для данного потока. Может вернуть
NULLесли API GILState не использовалось в текущем потоке. Обратите внимание, что основной поток всегда имеет такое состояние потока, даже если не был вызван авто-создающий вызов состояния потока в основном потоке. Это в основном вспомогательная/диагностическая функция.
-
int PyGILState_Check() -
Возвращает
1если текущий поток держит GIL, и0в противном случае. Эту функцию можно вызывать из любого потока в любое время. Она вернёт1, только если состояние потока Python было инициализировано и в данный момент поток держит GIL. Это в основном вспомогательная/диагностическая функция. Она может быть полезна, например, в контекстах обратного вызова или функциях выделения памяти, когда знание о том, что GIL заблокирован, позволяет вызывающей стороне выполнять чувствительные действия или иначе вести себя по-другому.Введено в версии 3.4.
Следующие макросы обычно используются без заключительной точки с запятой; примеры использования см. в дистрибутиве исходного кода Python.
-
Py_BEGIN_ALLOW_THREADS -
Часть Стабильного ABI.
Эта макрокоманда раскрывается как
{ PyThreadState *_save; _save = PyEval_SaveThread();. Обратите внимание, что она содержит открывающую фигурную скобку; она должна быть согласована с последующей макрокомандойPy_END_ALLOW_THREADS. Дополнительные сведения об этой макрокоманде см. выше.
-
Py_END_ALLOW_THREADS -
Часть Стабильного ABI.
Эта макрокоманда раскрывается как
PyEval_RestoreThread(_save); }. Обратите внимание, что она содержит закрывающую фигурную скобку; она должна быть согласована с предыдущей макрокомандойPy_BEGIN_ALLOW_THREADS. Дополнительные сведения об этой макрокоманде см. выше.
-
Py_BLOCK_THREADS -
Часть Стабильного ABI.
Эта макрокоманда раскрывается как
PyEval_RestoreThread(_save);: она эквивалентнаPy_END_ALLOW_THREADSбез закрывающей фигурной скобки.
-
Py_UNBLOCK_THREADS -
Часть Стабильного ABI.
Эта макрокоманда раскрывается как
_save = PyEval_SaveThread();: она эквивалентнаPy_BEGIN_ALLOW_THREADSбез открывающей фигурной скобки и объявления переменной.
API низкого уровня
Все следующие функции должны вызываться после Py_Initialize().
Изменено в версии 3.7: Py_Initialize() теперь инициализирует GIL.
-
PyInterpreterState *PyInterpreterState_New() -
Часть Стабильной ABI.
Создаёт новый объект состояния интерпретатора. Блокировка глобального интерпретатора не требуется, но может быть взята, если необходимо сериализовать вызовы этой функции.
Вызывает событие аудита
cpython.PyInterpreterState_Newбез аргументов.
-
void PyInterpreterState_Clear(PyInterpreterState *interp) -
Часть Стабильной ABI.
Сбрасывает всю информацию в объекте состояния интерпретатора. Необходимо удерживать блокировку глобального интерпретатора.
Вызывает событие аудита
cpython.PyInterpreterState_Clearбез аргументов.
-
void PyInterpreterState_Delete(PyInterpreterState *interp) -
Часть Стабильной ABI.
Уничтожает объект состояния интерпретатора. Блокировка глобального интерпретатора не требуется. Состояние интерпретатора должно быть сброшено с помощью предыдущего вызова
PyInterpreterState_Clear().
-
PyThreadState *PyThreadState_New(PyInterpreterState *interp) -
Часть Стабильной ABI.
Создаёт новый объект состояния потока, принадлежащий данному объекту интерпретатора. Блокировка глобального интерпретатора не требуется, но может быть взята, если необходимо сериализовать вызовы этой функции.
-
void PyThreadState_Clear(PyThreadState *tstate) -
Часть Стабильной ABI.
Сбрасывает всю информацию в объекте состояния потока. Блокировка глобального интерпретатора должна быть удерживаема.
Изменено в версии 3.9: Эта функция теперь вызывает колбэк
PyThreadState.on_delete. Ранее это происходило вPyThreadState_Delete().
-
void PyThreadState_Delete(PyThreadState *tstate) -
Часть Стабильной ABI.
Уничтожает объект состояния потока. Блокировка глобального интерпретатора не требуется. Состояние потока должно быть сброшено с помощью предыдущего вызова
PyThreadState_Clear().
-
void PyThreadState_DeleteCurrent(void) -
Уничтожает текущее состояние потока и освобождает блокировку глобального интерпретатора. Как и в
PyThreadState_Delete(), блокировка глобального интерпретатора не требуется. Состояние потока должно быть сброшено с помощью предыдущего вызоваPyThreadState_Clear().
-
PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate) -
Часть Стабильной ABI с версии 3.10.
Получает текущий фрейм состояния потока Python tstate.
Возвращает сильную ссылку. Возвращает
NULLесли в данный момент не выполняется никакой фрейм.См. также
PyEval_GetFrame().tstate не должен быть
NULL.Добавлена в версии 3.9.
-
uint64_t PyThreadState_GetID(PyThreadState *tstate) -
Часть Стабильной ABI с версии 3.10.
Получает уникальный идентификатор состояния потока Python tstate.
tstate не должен быть
NULL.Добавлена в версии 3.9.
-
PyInterpreterState *PyThreadState_GetInterpreter(PyThreadState *tstate) -
Часть Стабильной ABI с версии 3.10.
Получает интерпретатор состояния потока Python tstate.
tstate не должен быть
NULL.Добавлена в версии 3.9.
-
void PyThreadState_EnterTracing(PyThreadState *tstate) -
Приостанавливает отслеживание и профилирование в состоянии потока Python tstate.
Возобновить их можно с помощью функции
PyThreadState_LeaveTracing().Добавлена в версии 3.11.
-
void PyThreadState_LeaveTracing(PyThreadState *tstate) -
Возобновляет отслеживание и профилирование в состоянии потока Python tstate, приостановленное функцией
PyThreadState_EnterTracing().См. также функции
PyEval_SetTrace()иPyEval_SetProfile().Добавлена в версии 3.11.
-
PyInterpreterState *PyInterpreterState_Get(void) -
Часть Стабильной ABI с версии 3.9.
Получает текущий интерпретатор.
Выдаёт ошибку, если нет текущего состояния потока Python или текущего интерпретатора. Не может вернуть NULL.
Вызывающий должен удерживать GIL.
Добавлена в версии 3.9.
-
int64_t PyInterpreterState_GetID(PyInterpreterState *interp) -
Часть Стабильной ABI с версии 3.7.
Возвращает уникальный идентификатор интерпретатора. Если произошла ошибка, возвращается
-1и устанавливается ошибка.Вызывающий должен удерживать GIL.
Добавлена в версии 3.7.
-
PyObject *PyInterpreterState_GetDict(PyInterpreterState *interp) -
Часть Стабильной ABI с версии 3.8.
Возвращает словарь, в котором может храниться информация, специфичная для интерпретатора. Если функция возвращает
NULL, исключение не было поднято, и вызывающий должен считать, что словарь, специфичный для интерпретатора, недоступен.Это не замена для
PyModule_GetState(), которую расширения должны использовать для хранения специфичной для интерпретатора информации о состоянии.Добавлена в версии 3.8.
-
typedef PyObject *(*_PyFrameEvalFunction)(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag) -
Тип функции оценки фрейма.
Параметр throwflag используется методом
throw()генераторов: если ненулевой, обработать текущее исключение.Изменено в версии 3.9: Функция теперь принимает параметр tstate.
Изменено в версии 3.11: Параметр frame изменился с
PyFrameObject*на_PyInterpreterFrame*.
-
_PyFrameEvalFunction _PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp) -
Получает функцию оценки фрейма.
См. PEP 523 “Добавление API оценки фрейма в CPython”.
Добавлена в версии 3.9.
-
void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame) -
Устанавливает функцию оценки фрейма.
См. PEP 523 “Добавление API оценки фрейма в CPython”.
Добавлена в версии 3.9.
-
PyObject *PyThreadState_GetDict() -
Значение возврата: Заимствованная ссылка. Часть Стабильного ABI.
Возвращает словарь, в котором расширения могут хранить информацию о состоянии, специфичную для потока. Каждое расширение должно использовать уникальный ключ для хранения состояния в словаре. Разрешено вызывать эту функцию, когда состояние текущего потока недоступно. Если эта функция возвращает
NULL, исключение не было поднято, и вызывающая сторона должна предположить, что текущее состояние потока недоступно.
-
int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) -
Часть Стабильного ABI.
Асинхронно поднимает исключение в потоке. Аргумент id — идентификатор целевого потока; exc — объект исключения, который должен быть поднят. Эта функция не захватывает никаких ссылок на exc. Чтобы предотвратить неправильное использование, вы должны написать собственное расширение C для вызова этой функции. Должна вызываться с захваченным GIL. Возвращает количество изменённых состояний потока; обычно это один, но будет ноль, если идентификатор потока не найден. Если exc равно
NULL, ожидаемое исключение (если таковое имеется) для потока очищается. Исключений не поднимается.Изменено в версии 3.7: Тип параметра id изменён с long на unsigned long.
-
void PyEval_AcquireThread(PyThreadState *tstate) -
Часть Стабильного ABI.
Захватывает блокировку глобального интерпретатора и устанавливает текущее состояние потока на tstate, которое не должно быть
NULL. Блокировка должна быть создана ранее. Если этот поток уже имеет блокировку, возникает тупиковая ситуация.Примечание
Вызов этой функции из потока, когда среда выполнения завершает работу, приведёт к завершению потока, даже если поток не был создан Python. Вы можете использовать
_Py_IsFinalizing()илиsys.is_finalizing(), чтобы проверить, завершает ли интерпретатор работу, перед вызовом этой функции, чтобы избежать нежелательного завершения.Изменено в версии 3.8: Обновлено для согласованности с
PyEval_RestoreThread(),Py_END_ALLOW_THREADS()иPyGILState_Ensure(), и завершить текущий поток, если вызвано во время завершения работы интерпретатора.PyEval_RestoreThread()— функция более высокого уровня, которая всегда доступна (даже когда потоки не были инициализированы).
-
void PyEval_ReleaseThread(PyThreadState *tstate) -
Часть Стабильного ABI.
Сбрасывает текущее состояние потока на
NULLи освобождает блокировку глобального интерпретатора. Блокировка должна быть создана ранее и должна быть захвачена текущим потоком. Аргумент tstate, который не должен бытьNULL, используется только для проверки того, что он представляет текущее состояние потока — если это не так, то сообщается об ошибке.PyEval_SaveThread()— функция более высокого уровня, которая всегда доступна (даже когда потоки не были инициализированы).
-
void PyEval_AcquireLock() -
Часть Стабильного ABI.
Захватывает блокировку глобального интерпретатора. Блокировка должна быть создана ранее. Если этот поток уже имеет блокировку, возникает тупиковая ситуация.
Устарело начиная с версии 3.2: Эта функция не обновляет текущее состояние потока. Используйте
PyEval_RestoreThread()илиPyEval_AcquireThread()вместо неё.Примечание
Вызов этой функции из потока, когда среда выполнения завершает работу, приведёт к завершению потока, даже если поток не был создан Python. Вы можете использовать
_Py_IsFinalizing()илиsys.is_finalizing(), чтобы проверить, завершает ли интерпретатор работу, перед вызовом этой функции, чтобы избежать нежелательного завершения.Изменено в версии 3.8: Обновлено для согласованности с
PyEval_RestoreThread(),Py_END_ALLOW_THREADS()иPyGILState_Ensure(), и завершить текущий поток, если вызвано во время завершения работы интерпретатора.
-
void PyEval_ReleaseLock() -
Часть Стабильного ABI.
Освобождает блокировку глобального интерпретатора. Блокировка должна быть создана ранее.
Устарело начиная с версии 3.2: Эта функция не обновляет текущее состояние потока. Используйте
PyEval_SaveThread()илиPyEval_ReleaseThread()вместо неё.
Поддержка дочерних интерпретаторов
Хотя в большинстве случаев вы будете встраивать только один интерпретатор Python, есть случаи, когда вам нужно создать несколько независимых интерпретаторов в одном процессе и, возможно, даже в одной и той же потоке. Дочерние интерпретаторы позволяют это сделать.
«Главный» интерпретатор — это первый созданный, когда среда выполнения инициализируется. Обычно это единственный интерпретатор Python в процессе. В отличие от дочерних интерпретаторов, главный интерпретатор имеет уникальные глобальные для процесса обязанности, такие как обработка сигналов. Он также отвечает за выполнение во время инициализации среды выполнения и обычно является активным интерпретатором во время завершения среды выполнения. Функция PyInterpreterState_Main() возвращает указатель на его состояние.
Вы можете переключаться между дочерними интерпретаторами, используя функцию PyThreadState_Swap(). Вы можете создавать и уничтожать их с помощью следующих функций:
-
PyThreadState *Py_NewInterpreter() -
Часть Стабильной ABI.
Создает новый дочерний интерпретатор. Это (почти) полностью отдельная среда для выполнения кода Python. В частности, новый интерпретатор имеет отдельные, независимые версии всех импортированных модулей, включая фундаментальные модули
builtins,__main__иsys. Таблица загруженных модулей (sys.modules) и путь поиска модулей (sys.path) также разделены. Новая среда не имеет переменнойsys.argv. Она имеет новые стандартные потоки ввода/вывода файлы объектовsys.stdin,sys.stdoutиsys.stderr(однако они ссылаются на те же базовые дескрипторы файлов).Значение возврата указывает на первый созданный поток состояния в новом дочернем интерпретаторе. Это состояние потока создается в текущем состоянии потока. Обратите внимание, что фактически поток не создается; см. обсуждение состояний потоков ниже. Если создание нового интерпретатора не удалось, возвращается
NULL; исключение не устанавливается, так как состояние исключения хранится в текущем состоянии потока, и может не быть текущего состояния потока. (Как и все другие функции API Python/C, глобальная блокировка интерпретатора должна быть заблокирована перед вызовом этой функции и все еще заблокирована при ее возвращении; однако, в отличие от большинства других функций API Python/C, при входе не обязательно должно быть текущее состояние потока.)Модули расширения совместно используются между (под-)интерпретаторами следующим образом:
- Для модулей, использующих многофазную инициализацию, например,
PyModule_FromDefAndSpec(), для каждого интерпретатора создается и инициализируется отдельный объект модуля. Только статические и глобальные переменные на уровне C совместно используются между этими объектами модуля. -
Для модулей, использующих однофазную инициализацию, например,
PyModule_Create(), в первый раз, когда определенный модуль расширения импортируется, он инициализируется обычно, и (неглубокая) копия словаря модуля скрывается. Когда тот же модуль расширения импортируется другим (под-)интерпретатором, инициализируется новый модуль и заполняется содержимым этой копии; функцияinitмодуля не вызывается. Таким образом, объекты в словаре модуля оказываются общими для (под-)интерпретаторов, что может привести к нежелательному поведению (см. Проблемы и замечания ниже).Обратите внимание, что это отличается от того, что происходит, когда модуль расширения импортируется после того, как интерпретатор был полностью повторно инициализирован путем вызова
Py_FinalizeEx()иPy_Initialize(); в этом случае функцияinitmoduleмодуля вызывается снова. Как и при многофазной инициализации, это означает, что только статические и глобальные переменные на уровне C совместно используются между этими модулями.
- Для модулей, использующих многофазную инициализацию, например,
-
void Py_EndInterpreter(PyThreadState *tstate) -
Часть Стабильной ABI.
Уничтожает (под-)интерпретатор, представленный заданным состоянием потока. Заданное состояние потока должно быть текущим состоянием потока. См. обсуждение состояний потоков ниже. При возвращении вызова текущее состояние потока —
NULL. Все состояния потоков, связанные с этим интерпретатором, уничтожаются. (Глобальная блокировка интерпретатора должна быть заблокирована перед вызовом этой функции и все еще заблокирована при ее возвращении.)Py_FinalizeEx()уничтожит все дочерние интерпретаторы, которые не были явно уничтожены к этому моменту.
Проблемы и замечания
Поскольку дочерние интерпретаторы (и главный интерпретатор) являются частью одного процесса, изоляция между ними несовершенна — например, используя операции с файлами низкого уровня, такие как os.close(), они могут (случайно или злонамеренно) влиять на открытые файлы друг друга. Из-за того, как модули расширения совместно используются между (под-)интерпретаторами, некоторые модули расширения могут работать неправильно; это особенно вероятно при использовании однофазной инициализации или (статических) глобальных переменных. Возможно вставить объекты, созданные в одном под-интерпретаторе, в пространство имен другого (под-)интерпретатора; этого следует по возможности избегать.
Особое внимание следует уделить, чтобы избежать совместного использования пользовательских функций, методов, экземпляров или классов между под-интерпретаторами, так как операции импорта, выполняемые такими объектами, могут повлиять на словарь загруженных модулей неправильного (под-)интерпретатора. Не менее важно избегать совместного использования объектов, доступ к которым может быть выполнен через вышеупомянутые.
Также обратите внимание, что сочетание этой функциональности с PyGILState_* API является деликатным, так как эти API предполагают взаимно однозначное соответствие между состояниями потоков Python и потоками на уровне ОС, предположение, нарушаемое наличием под-интерпретаторов. Настоятельно рекомендуется не переключаться между под-интерпретаторами между парой вызовов PyGILState_Ensure() и PyGILState_Release(). Кроме того, модули расширения (например, ctypes), использующие эти API для вызова кода Python из потоков, созданных не в Python, вероятно, сломаются при использовании под-интерпретаторов.
Асинхронные уведомления
Предоставляется механизм для отправки асинхронных уведомлений в главный поток интерпретатора. Эти уведомления представляют собой указатель на функцию и аргумент указателя на void.
-
int Py_AddPendingCall(int (*func)(void*), void *arg) -
Часть Стабильной ABI.
Планирует вызов функции из главного потока интерпретатора. При успехе возвращается
0, и func помещается в очередь для вызова в главном потоке. При неудаче возвращается-1, без установки какого-либо исключения.При успешном добавлении в очередь func будет в конечном итоге вызван из главного потока интерпретатора с аргументом arg. Он будет вызван асинхронно по отношению к обычно выполняемому коду Python, но с соблюдением обоих этих условий:
- на границе байт-кода;
- с главным потоком, удерживающим глобальную блокировку интерпретатора (func, таким образом, может использовать весь API C).
func должен возвращать
0при успехе или-1при ошибке с установленным исключением. func не будет прерываться для выполнения другого асинхронного уведомления рекурсивно, но его все равно можно прервать для переключения потоков, если глобальная блокировка интерпретатора освобождается.Эта функция не требует текущего состояния потока для выполнения и не требует глобальной блокировки интерпретатора.
Чтобы вызвать эту функцию в под-интерпретаторе, вызывающий должен удерживать GIL. В противном случае функция func может быть запланирована для вызова из неправильного интерпретатора.
Предупреждение
Это функция низкого уровня, полезная только в очень специфических случаях. Нет гарантии, что func будет вызвана как можно быстрее. Если главный поток занят выполнением системного вызова, func не будет вызвана до возвращения системного вызова. Эта функция, как правило, не подходит для вызова кода Python из произвольных C-потоков. Вместо этого используйте API PyGILState.
Изменено в версии 3.9: Если эта функция вызывается в под-интерпретаторе, функция func теперь запланирована для вызова из под-интерпретатора, а не из главного интерпретатора. Каждый под-интерпретатор теперь имеет свой собственный список запланированных вызовов.
Добавлена в версии 3.1.
Профилирование и отслеживание
Интерпретатор Python предоставляет некоторую поддержку низкого уровня для присоединения средств профилирования и отслеживания выполнения. Они используются для профилирования, отладки и анализа покрытия.
Этот интерфейс C позволяет коду профилирования или отслеживания избежать накладных расходов вызовов через вызываемые объекты на уровне Python, вместо этого выполняя прямой вызов C-функции. Существенные атрибуты механизма не изменились; интерфейс позволяет устанавливать функции отслеживания на уровне потока, и основные события, сообщаемые функции отслеживания, такие же, как и сообщаются функциям отслеживания на уровне Python в предыдущих версиях.
-
typedef int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) -
Тип функции отслеживания, зарегистрированной с помощью
PyEval_SetProfile()иPyEval_SetTrace(). Первый параметр — объект, переданный функции регистрации как obj, frame — объект фрейма, к которому относится событие, what — одна из константPyTrace_CALL,PyTrace_EXCEPTION,PyTrace_LINE,PyTrace_RETURN,PyTrace_C_CALL,PyTrace_C_EXCEPTION,PyTrace_C_RETURNилиPyTrace_OPCODE, а arg зависит от значения what:Значение what
Значение arg
Всегда
Py_None.Информация об исключении, возвращаемая
sys.exc_info().Всегда
Py_None.Значение, возвращаемое вызывающей стороне, или
NULLесли оно вызвано исключением.Объект функции, который вызывается.
Объект функции, который вызывается.
Объект функции, который вызывается.
Всегда
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_LINEPyTrace_OPCODEиPyTrace_EXCEPTION.См. также функцию
sys.setprofile().Вызывающая сторона должна удерживать GIL.
-
void PyEval_SetTrace(Py_tracefunc func, PyObject *obj) -
Установить функцию отслеживания на func. Это аналогично
PyEval_SetProfile(), за исключением того, что функция отслеживания получает события номера строки и события на уровне оператора, но не получает никаких событий, связанных с вызовами C-функций. Любая функция отслеживания, зарегистрированная с помощьюPyEval_SetTrace(), не будет получатьPyTrace_C_CALL,PyTrace_C_EXCEPTIONилиPyTrace_C_RETURNкак значение для параметра what.См. также функцию
sys.settrace().Вызывающая сторона должна удерживать GIL.
Поддержка расширенного отладчика
Эти функции предназначены только для использования расширенными инструментами отладки.
-
PyInterpreterState *PyInterpreterState_Head() -
Возвращает объект состояния интерпретатора в начале списка всех таких объектов.
-
PyInterpreterState *PyInterpreterState_Main() -
Возвращает главный объект состояния интерпретатора.
-
PyInterpreterState *PyInterpreterState_Next(PyInterpreterState *interp) -
Возвращает следующий объект состояния интерпретатора после interp из списка всех таких объектов.
-
PyThreadState *PyInterpreterState_ThreadHead(PyInterpreterState *interp) -
Возвращает указатель на первый объект
PyThreadStateв списке потоков, связанных с интерпретатором interp.
-
PyThreadState *PyThreadState_Next(PyThreadState *tstate) -
Возвращает следующий объект состояния потока после tstate из списка всех таких объектов, принадлежащих тому же объекту
PyInterpreterState.
Поддержка локального хранения данных потоков
Интерпретатор Python предоставляет низкоуровневую поддержку локального хранения данных потоков (TLS), которая оборачивает базовую реализацию TLS для поддержки API локального хранения данных потоков на уровне Python (threading.local). API CPython на C-уровне похожи на предлагаемые pthreads и Windows: используйте ключ потока и функции для ассоциации значения void* с каждым потоком.
Флаг блокировки GIL не требуется при вызове этих функций; они обеспечивают собственную блокировку.
Обратите внимание, что Python.h не включает объявление API TLS; вам нужно включить pythread.h для использования локального хранения данных потоков.
Примечание
Ни одна из этих функций API не обрабатывает управление памятью за значениями void*. Вы должны выделять и освобождать их самостоятельно. Если значения void* оказываются PyObject*, эти функции также не выполняют операции с счётчиком ссылок.
API локального хранения данных потоков (TSS)
API TSS введён для замены использования существующего API TLS в интерпретаторе CPython. Этот API использует новый тип Py_tss_t вместо int для представления ключей потока.
Введено в версии 3.7.
См. также
«Новый C-API для локального хранения данных потоков в CPython» (PEP 539)
-
type Py_tss_t -
Эта структура данных представляет состояние ключа потока, определение которого может зависеть от реализации базового TLS, и она имеет внутреннее поле, представляющее состояние инициализации ключа. В этой структуре нет публичных членов.
Когда Py_LIMITED_API не определён, статическое выделение этого типа с помощью
Py_tss_NEEDS_INITразрешено.
-
Py_tss_NEEDS_INIT -
Этот макрос расширяется до инициализатора переменных типа
Py_tss_t. Обратите внимание, что этот макрос не будет определён с Py_LIMITED_API.
Динамическое выделение
Динамическое выделение Py_tss_t, необходимое в модулях расширения, построенных с Py_LIMITED_API, где статическое выделение этого типа невозможно из-за того, что его реализация невидима во время компиляции.
-
Py_tss_t *PyThread_tss_alloc() -
Часть Стабильной ABI с версии 3.7.
Возвращает значение, которое соответствует значению, инициализированному с помощью
Py_tss_NEEDS_INIT, илиNULLв случае неудачи при динамическом выделении.
-
void PyThread_tss_free(Py_tss_t *key) -
Часть Стабильной ABI с версии 3.7.
Освобождает заданный key, выделенный функцией
PyThread_tss_alloc(), после вызоваPyThread_tss_delete()для обеспечения того, что любые связанные локальные переменные потоков были отвязаны. Это ничто, если аргумент key равенNULL.Примечание
Освобождённый ключ становится висячей ссылкой. Вы должны сбросить ключ на
NULL.
Методы
Параметр key этих функций не должен быть NULL. Кроме того, поведение PyThread_tss_set() и PyThread_tss_get() не определено, если заданный Py_tss_t не был инициализирован PyThread_tss_create().
-
int PyThread_tss_is_created(Py_tss_t *key) -
Часть Стабильной ABI с версии 3.7.
Возвращает ненулевое значение, если заданный
Py_tss_tбыл инициализированPyThread_tss_create().
-
int PyThread_tss_create(Py_tss_t *key) -
Часть Стабильной ABI с версии 3.7.
Возвращает нулевое значение при успешной инициализации ключа TSS. Поведение не определено, если значение, на которое указывает аргумент key, не инициализировано с помощью
Py_tss_NEEDS_INIT. Эту функцию можно вызывать повторно для одного и того же ключа – вызов для уже инициализированного ключа ничего не делает и сразу возвращает успех.
-
void PyThread_tss_delete(Py_tss_t *key) -
Часть Стабильной ABI с версии 3.7.
Уничтожает ключ TSS, чтобы забыть значения, связанные с ключом во всех потоках, и изменить состояние инициализации ключа на неинициализированное. Уничтоженный ключ может быть инициализирован повторно функцией
PyThread_tss_create(). Эту функцию можно вызывать повторно для одного и того же ключа – вызов для уже уничтоженного ключа ничего не делает.
-
int PyThread_tss_set(Py_tss_t *key, void *value) -
Часть Стабильной ABI с версии 3.7.
Возвращает нулевое значение, чтобы указать на успешное связывание значения void* с ключом TSS в текущем потоке. Каждый поток имеет отдельное отображение ключа на значение void*.
-
void *PyThread_tss_get(Py_tss_t *key) -
Часть Стабильной ABI с версии 3.7.
Возвращает значение void*, связанное с ключом TSS в текущем потоке. Возвращает
NULL, если значению с ключом в текущем потоке не назначено.
API локального хранения данных потоков (TLS)
Устарело начиная с версии 3.7: Этот API заменён API хранения данных для конкретного потока (TSS).
Примечание
Эта версия API не поддерживает платформы, где ключ native TLS определён таким образом, что его нельзя безопасно привести к типу int. На таких платформах, PyThread_create_key() будет возвращать немедленный результат с ошибкой, а другие функции TLS будут работать как no-ops на таких платформах.
Из-за проблемы совместимости, описанной выше, эта версия API не должна использоваться в новом коде.
-
int PyThread_create_key() - Часть стабильной ABI.
-
void PyThread_delete_key(int key) - Часть стабильной ABI.
-
int PyThread_set_key_value(int key, void *value) - Часть стабильной ABI.
-
void *PyThread_get_key_value(int key) - Часть стабильной ABI.
-
void PyThread_delete_key_value(int key) - Часть стабильной ABI.
-
void PyThread_ReInitTLS() - Часть стабильной ABI.
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/c-api/init.html