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