Содержание страницы
Инициализация, финализация и потоки¶Initialization, Finalization, and Threads
См. также Конфигурация инициализации Python.
Перед инициализацией Python¶Before Python Initialization
В приложении, внедряющем 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().
Глобальные переменные конфигурации¶Global configuration variables
В 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_IsolatedFlag¶ Запуск Python в изолированном режиме. В изолированном режиме
sys.pathне содержит ни каталог скрипта, ни каталог site-packages пользователя.Устанавливается опцией
-I.Новое в версии 3.4.
-
int
Py_LegacyWindowsFSEncodingFlag¶ Если флаг ненулевой, для кодировки файловой системы используется
mbcsкодировка вместо UTF-8.Устанавливается в
1, если переменная окруженияPYTHONLEGACYWINDOWSFSENCODINGустановлена в непустую строку.См. PEP 529 для подробностей.
Доступность: Windows.
-
int
Py_LegacyWindowsStdioFlag¶ Если флаг ненулевой, используется
io.FileIOвместоWindowsConsoleIOдляsysстандартных потоков.Устанавливается в
1, если переменная окруженияPYTHONLEGACYWINDOWSSTDIOустановлена в непустую строку.См. PEP 528 для подробностей.
Доступность: Windows.
-
int
Py_NoSiteFlag¶ Отключает импорт модуля
siteи связанные с ним 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.
Инициализация и завершение работы интерпретатора¶Initializing and finalizing the interpreter
-
void
Py_Initialize()¶ Инициализирует интерпретатор Python. В приложении, встраивающем Python, эту функцию следует вызывать до использования любых других функций Python/C API; за несколькими исключениями обращайтесь к Before Python Initialization.
Эта функция инициализирует таблицу загруженных модулей (
sys.modules) и создает фундаментальные модулиbuiltins,__main__иsys. Она также инициализирует путь поиска модулей (sys.path). Она не устанавливаетsys.argv; для этого используйтеPySys_SetArgvEx(). При повторном вызове (без предварительного вызоваPy_FinalizeEx()) ничего не происходит. Возвращаемого значения нет; если инициализация не удалась, это фатальная ошибка.Примечание
В Windows изменяет режим консоли с
O_TEXTнаO_BINARY, что также повлияет на использование консоли из других приложений на C Runtime.
-
void
Py_InitializeEx(int initsigs)¶ Эта функция работает как
Py_Initialize(), если initsigs равно1. Если initsigs равно0, она пропускает регистрацию обработчиков сигналов при инициализации, что может быть полезно при встраивании Python.
-
int
Py_IsInitialized()¶ Возвращает true (ненулевое значение), если интерпретатор Python был инициализирован, и false (ноль), если нет. После вызова
Py_FinalizeEx()функция возвращает false до тех пор, пока не будет снова вызванаPy_Initialize().
-
int
Py_FinalizeEx()¶ Отменяет все инициализации, выполненные
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()¶ Это обратно совместимая версия
Py_FinalizeEx(), которая игнорирует возвращаемое значение.
Общепроцессные параметры¶Process-wide parameters
-
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)¶ Эту функцию следует вызвать до первого вызова
Py_Initialize(), если она вообще вызывается. Она сообщает интерпретатору значение аргументаargv[0]функцииmain()программы (преобразованное в широкие символы). Это используетсяPy_GetPath()и некоторыми другими функциями ниже для поиска библиотек времени выполнения Python относительно исполняемого файла интерпретатора. Значение по умолчанию –'python'. Аргумент должен указывать на строку широких символов, завершающуюся нулём, в статической памяти, содержимое которой не изменится за время выполнения программы. Никакой код в интерпретаторе Python не изменит содержимое этой памяти.Используйте
Py_DecodeLocale()для декодирования строки байтов, чтобы получить строкуwchar_*.
-
wchar*
Py_GetProgramName()¶ Возвращает имя программы, установленное с помощью
Py_SetProgramName(), или значение по умолчанию. Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение.
-
wchar_t*
Py_GetPrefix()¶ Возвращает префикс для установленных платформонезависимых файлов. Он определяется по ряду сложных правил из имени программы, установленного с помощью
Py_SetProgramName(), и некоторых переменных окружения; например, если имя программы –'/usr/local/bin/python', префикс –'/usr/local'. Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение. Это соответствует переменной prefix в корневомMakefileи аргументу--prefixсценария configure во время сборки. Значение доступно в коде Python какsys.prefix. Полезен только в Unix. Смотрите также следующую функцию.
-
wchar_t*
Py_GetExecPrefix()¶ Возвращает 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 отличается от префикса (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будет отдельной файловой системой для каждой платформы.
-
wchar_t*
Py_GetProgramFullPath()¶ Возвращает полное имя программы исполняемого файла Python; оно вычисляется как побочный эффект при получении пути поиска модулей по умолчанию из имени программы (заданного с помощью
Py_SetProgramName()выше). Возвращаемая строка указывает на статическую память; вызывающий не должен изменять её значение. Значение доступно коду Python какsys.executable.
-
wchar_t*
Py_GetPath()¶ Возвращает путь поиска модулей по умолчанию; он вычисляется из имени программы (заданного с помощью
Py_SetProgramName()выше) и некоторых переменных окружения. Возвращаемая строка состоит из последовательности имён каталогов, разделённых символом-разделителем, зависящим от платформы. Символ-разделитель –':'в Unix и Mac OS X,';'в Windows. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Списокsys.pathинициализируется этим значением при запуске интерпретатора; впоследствии его можно (и обычно так и делают) изменить, чтобы изменить путь поиска для загрузки модулей.
-
void
Py_SetPath(const wchar_t *)¶ Устанавливает путь поиска модулей по умолчанию. Если эта функция вызывается до
Py_Initialize(), тоPy_GetPath()не будет пытаться вычислить путь поиска по умолчанию, а вместо этого использует предоставленный. Это полезно, если Python встраивается в приложение, которое полностью знает расположение всех модулей. Компоненты пути должны быть разделены символом-разделителем, зависящим от платформы:':'в Unix и Mac OS X,';'в Windows.Это также приводит к тому, что
sys.executableустанавливается в полный путь программы (см.Py_GetProgramFullPath()), аsys.prefixиsys.exec_prefixстановятся пустыми. Вызывающий может изменить их при необходимости после вызоваPy_Initialize().Используйте
Py_DecodeLocale()для декодирования строки байтов, чтобы получить строкуwchar_*.Аргумент path копируется внутри, поэтому вызывающий может освободить его после завершения вызова.
Изменено в версии 3.8: Теперь для
sys.executableиспользуется полный путь программы, а не имя программы.
-
const char*
Py_GetVersion()¶ Возвращает версию данного интерпретатора Python. Это строка, которая выглядит примерно так:
"3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]"
Первое слово (до первого пробела) – это текущая версия Python; первые три символа – это major и minor версии, разделённые точкой. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно в коде Python как
sys.version.
-
const char*
Py_GetPlatform()¶ Возвращает идентификатор платформы для текущей платформы. В Unix он формируется из «официального» названия операционной системы, приведённого к нижнему регистру, за которым следует номер основной версии; например, для Solaris 2.x (также известной как SunOS 5.x) значением является
'sunos5'. В Mac OS X это'darwin'. В Windows это'win'. Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Это значение доступно из кода Python какsys.platform.
-
const char*
Py_GetCopyright()¶ Возвращает официальную строку авторских прав для текущей версии Python, например
'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Значение доступно в коде Python как
sys.copyright.
-
const char*
Py_GetCompiler()¶ Возвращает указание компилятора, использованного для сборки текущей версии Python, в квадратных скобках, например:
"[GCC 2.7.2.2]"Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Значение доступно коду Python как часть переменной
sys.version.
-
const char*
Py_GetBuildInfo()¶ Возвращает информацию о номере сборки, дате и времени сборки текущего экземпляра интерпретатора Python, например
"#67, Aug 1 1997, 22:34:28"Возвращаемая строка указывает на статическую память; вызывающий код не должен изменять её значение. Значение доступно коду Python как часть переменной
sys.version.
-
void
PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)¶ Устанавливает
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)¶ Эта функция работает как
PySys_SetArgvEx()с updatepath, установленным в1, если только интерпретатор python не был запущен с-I.Используйте
Py_DecodeLocale()для декодирования строки байтов, чтобы получить строкуwchar_*.Изменено в версии 3.4: Значение updatepath зависит от
-I.
-
void
Py_SetPythonHome(const wchar_t *home)¶ Устанавливает домашний каталог по умолчанию, то есть расположение стандартных библиотек Python. См.
PYTHONHOMEдля пояснения значения строки аргумента.Аргумент должен указывать на строку символов, завершающуюся нулём, в статической памяти, содержимое которой не будет изменяться в течение всего времени выполнения программы. Никакой код в интерпретаторе Python не будет менять содержимое этой памяти.
Используйте
Py_DecodeLocale()для декодирования строки байтов, чтобы получить строкуwchar_*.
-
w_char*
Py_GetPythonHome()¶ Возвращает «домашний» каталог по умолчанию, то есть значение, установленное предыдущим вызовом
Py_SetPythonHome(), или значение переменной окруженияPYTHONHOME, если она задана.
Состояние потока и глобальная блокировка интерпретатора¶Thread State and the Global Interpreter Lock
Интерпретатор Python не является полностью потокобезопасным. Для поддержки многопоточных программ на Python существует глобальная блокировка, называемая глобальной блокировкой интерпретатора или GIL, которую текущий поток должен удерживать перед тем, как безопасно обращаться к объектам Python. Без этой блокировки даже простейшие операции могут вызывать проблемы в многопоточной программе: например, когда два потока одновременно увеличивают счётчик ссылок одного и того же объекта, счётчик может в итоге увеличиться только один раз вместо двух.
Поэтому существует правило: только поток, захвативший GIL, может работать с объектами Python или вызывать функции Python/C API. Для эмуляции параллелизма выполнения интерпретатор регулярно пытается переключать потоки (см. sys.setswitchinterval()). Блокировка также освобождается вокруг потенциально блокирующих операций ввода-вывода, таких как чтение или запись файла, чтобы тем временем могли работать другие потоки Python.
Интерпретатор Python хранит некоторую служебную информацию, специфичную для потока, в структуре данных, называемой PyThreadState. Существует также одна глобальная переменная, указывающая на текущий PyThreadState: её можно получить с помощью PyThreadState_Get().
Освобождение GIL из кода расширения¶Releasing the GIL from extension code
Большая часть кода расширения, работающего с 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¶Non-Python created threads
Когда потоки создаются с помощью специализированных Python API (например, модуля threading), с ними автоматически связывается состояние потока, и приведённый выше код корректен. Однако, когда потоки создаются из C (например, сторонней библиотекой с собственным управлением потоками), они не удерживают GIL и для них не существует структуры состояния потока.
Если необходимо вызвать код Python из этих потоков (часто это будет частью API колбэков, предоставляемого упомянутой сторонней библиотекой), сначала нужно зарегистрировать эти потоки в интерпретаторе, создав структуру данных состояния потока, затем захватить GIL и, наконец, сохранить указатель на их состояние потока, прежде чем можно будет начать использовать Python/C API. После завершения следует сбросить указатель состояния потока, освободить GIL и освободить структуру данных состояния потока.
Функции PyGILState_Ensure() и PyGILState_Release() делают всё вышеописанное автоматически. Типичный способ вызова Python из потока C:
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
/* Выполнить действия Python здесь. */
result = CallSomeFunction();
/* вычислить результат или обработать исключение */
/* Освободить поток. После этой точки API Python не допускается. */
PyGILState_Release(gstate);
Обратите внимание, что функции PyGILState_*() предполагают наличие только одного глобального интерпретатора (создаваемого автоматически с помощью Py_Initialize()). Python поддерживает создание дополнительных интерпретаторов (с помощью Py_NewInterpreter()), но смешивание нескольких интерпретаторов и API PyGILState_*() не поддерживается.
Предостережения относительно fork()¶Cautions about fork()
Ещё одна важная особенность потоков – их поведение при вызове C fork(). На большинстве систем с fork() после
fork процесса остаётся только тот поток, который вызвал fork. Это
оказывает конкретное влияние как на обработку блокировок, так и на всё сохранённое состояние
в среде выполнения CPython.
То, что остаётся только «текущий» поток, означает, что любые блокировки, удерживаемые другими потоками, никогда не будут освобождены. Python решает эту проблему для os.fork(), захватывая блокировки, которые использует внутри, до вызова fork и освобождая их после. Кроме того, он сбрасывает любые объекты блокировок в дочернем процессе. При расширении или встраивании Python невозможно сообщить Python о дополнительных (не-Python) блокировках, которые необходимо захватить до fork или сбросить после. Для достижения того же эффекта потребуется использовать средства ОС, такие как pthread_atfork(). Кроме того, при расширении или встраивании Python вызов fork() напрямую, а не через os.fork() (и возврат в Python или вызов Python) может привести к взаимоблокировке из-за того, что одна из внутренних блокировок Python удерживается потоком, который перестаёт существовать после fork. PyOS_AfterFork_Child() пытается сбросить необходимые блокировки, но не всегда может это сделать.
Тот факт, что все остальные потоки исчезают, также означает, что состояние среды выполнения CPython должно быть правильно очищено, что и делает os.fork(). Это означает завершение всех остальных объектов PyThreadState, принадлежащих текущему интерпретатору, и всех остальных объектов PyInterpreterState. Из-за этого и особой природы «главного» интерпретатора, fork() следует вызывать только в «главном» потоке этого интерпретатора, где изначально была инициализирована глобальная среда выполнения CPython. Единственное исключение – если exec() будет вызван сразу после.
API высокого уровня¶High-level API
Это наиболее часто используемые типы и функции при написании кода C-расширения или при встраивании интерпретатора Python:
-
PyInterpreterState¶ Эта структура данных представляет состояние, совместно используемое несколькими взаимодействующими потоками. Потоки, принадлежащие одному интерпретатору, разделяют администрирование модулей и несколько других внутренних элементов. В этой структуре нет открытых членов.
Потоки, принадлежащие разным интерпретаторам, изначально не разделяют ничего, кроме состояния процесса, такого как доступная память, открытые файловые дескрипторы и т.п. Глобальная блокировка интерпретатора также разделяется всеми потоками, независимо от того, какому интерпретатору они принадлежат.
-
PyThreadState¶ Эта структура данных представляет состояние одного потока. Единственным открытым членом данных является
interp(PyInterpreterState *), который указывает на состояние интерпретатора этого потока.
-
void
PyEval_InitThreads()¶ Инициализирует и захватывает глобальную блокировку интерпретатора. Должна вызываться в главном потоке перед созданием второго потока или выполнением любых других операций с потоками, таких как
PyEval_ReleaseThread(tstate). Перед вызовомPyEval_SaveThread()илиPyEval_RestoreThread()это не требуется.При повторном вызове эта функция ничего не делает.
Изменено в версии 3.7: Теперь эта функция вызывается
Py_Initialize(), так что вам больше не нужно вызывать её самостоятельно.Изменено в версии 3.2: Эту функцию больше нельзя вызывать до
Py_Initialize().
-
int
PyEval_ThreadsInitialized()¶ Возвращает ненулевое значение, если
PyEval_InitThreads()был вызван. Эту функцию можно вызывать без удержания GIL, поэтому её можно использовать для избежания вызовов API блокировок при однопоточном выполнении.Изменено в версии 3.7: теперь GIL инициализируется с помощью
Py_Initialize().
-
PyThreadState*
PyEval_SaveThread()¶ Освобождает глобальную блокировку интерпретатора (если она была создана) и сбрасывает состояние потока на
NULL, возвращая предыдущее состояние потока (которое не равноNULL). Если блокировка была создана, текущий поток должен был её захватить.
-
void
PyEval_RestoreThread(PyThreadState *tstate)¶ Захватывает глобальную блокировку интерпретатора (если она была создана) и устанавливает состояние потока в tstate, которое не должно быть
NULL. Если блокировка была создана, текущий поток не должен был её захватить, иначе возникает взаимоблокировка.Примечание
Вызов этой функции из потока в момент завершения работы среды выполнения приведёт к завершению потока, даже если поток не был создан Python. Для проверки того, завершается ли интерпретатор, перед вызовом этой функции можно использовать
_Py_IsFinalizing()илиsys.is_finalizing(), чтобы избежать нежелательного завершения.
-
PyThreadState*
PyThreadState_Get()¶ Возвращает текущее состояние потока. Глобальная блокировка интерпретатора должна быть захвачена. Если текущее состояние потока равно
NULL, вызывается фатальная ошибка (так что вызывающему коду не нужно проверять наNULL).
-
PyThreadState*
PyThreadState_Swap(PyThreadState *tstate)¶ Заменяет текущее состояние потока на состояние потока, заданное аргументом tstate, который может быть
NULL. Глобальная блокировка интерпретатора должна быть удержана и не освобождается.
Следующие функции используют локальное хранилище потока и несовместимы с подынтерпретаторами:
-
PyGILState_STATE
PyGILState_Ensure()¶ Обеспечивает, что текущий поток готов к вызову Python C API независимо от текущего состояния 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)¶ Освобождает любые ресурсы, полученные ранее. После этого вызова состояние Python будет таким же, как до соответствующего вызова
PyGILState_Ensure()(но обычно это состояние неизвестно вызывающему, поэтому используется GILState API).Каждый вызов
PyGILState_Ensure()должен сопровождаться вызовомPyGILState_Release()в том же потоке.
-
PyThreadState*
PyGILState_GetThisThreadState()¶ Возвращает состояние текущего потока. Может вернуть
NULL, если на текущем потоке не использовался GILState API. Обратите внимание, что главный поток всегда имеет такое состояние, даже если для него не вызывался auto-thread-state. Это вспомогательная/диагностическая функция.
-
int
PyGILState_Check()¶ Возвращает
1, если текущий поток удерживает GIL, и0в противном случае. Эту функцию можно вызывать из любого потока в любое время. Только если состояние потока Python инициализировано и он в данный момент удерживает GIL, она вернёт1. Это в основном вспомогательная/диагностическая функция. Она может быть полезна, например, в контекстах колбэков или функциях выделения памяти, когда знание того, что GIL заблокирован, позволяет вызывающей стороне выполнять чувствительные действия или вести себя иначе.Новое в версии 3.4.
Следующие макросы обычно используются без точки с запятой в конце; примеры использования можно найти в дистрибутиве исходного кода Python.
-
Py_BEGIN_ALLOW_THREADS¶ Этот макрос раскрывается в
{ PyThreadState *_save; _save = PyEval_SaveThread();. Обратите внимание, что он содержит открывающую фигурную скобку; она должна быть сопоставлена с последующим макросомPy_END_ALLOW_THREADS. См. выше дополнительное обсуждение этого макроса.
-
Py_END_ALLOW_THREADS¶ Этот макрос раскрывается в
PyEval_RestoreThread(_save); }. Обратите внимание, что он содержит закрывающую фигурную скобку; она должна быть сопоставлена с предыдущим макросомPy_BEGIN_ALLOW_THREADS. См. выше дополнительное обсуждение этого макроса.
-
Py_BLOCK_THREADS¶ Этот макрос разворачивается в
PyEval_RestoreThread(_save);: он эквивалентенPy_END_ALLOW_THREADSбез закрывающей фигурной скобки.
-
Py_UNBLOCK_THREADS¶ Этот макрос разворачивается в
_save = PyEval_SaveThread();: он эквивалентенPy_BEGIN_ALLOW_THREADSбез открывающей фигурной скобки и объявления переменной.
Низкоуровневый API¶Low-level API
Все следующие функции должны вызываться после Py_Initialize().
Изменено в версии 3.7: Py_Initialize() теперь инициализирует GIL.
-
PyInterpreterState*
PyInterpreterState_New()¶ Создаёт новый объект состояния интерпретатора. Глобальная блокировка интерпретатора может не удерживаться, но может удерживаться, если необходимо сериализовать вызовы этой функции.
Возбуждает событие аудита
cpython.PyInterpreterState_Newбез аргументов.
-
void
PyInterpreterState_Clear(PyInterpreterState *interp)¶ Сбрасывает всю информацию в объекте состояния интерпретатора. Глобальная блокировка интерпретатора должна удерживаться.
Возбуждает событие аудита
cpython.PyInterpreterState_Clearбез аргументов.
-
void
PyInterpreterState_Delete(PyInterpreterState *interp)¶ Уничтожает объект состояния интерпретатора. Глобальная блокировка интерпретатора может не удерживаться. Состояние интерпретатора должно быть предварительно сброшено вызовом
PyInterpreterState_Clear().
-
PyThreadState*
PyThreadState_New(PyInterpreterState *interp)¶ Создаёт новый объект состояния потока, принадлежащий данному объекту интерпретатора. Глобальная блокировка интерпретатора может не удерживаться, но может удерживаться, если необходимо сериализовать вызовы этой функции.
-
void
PyThreadState_Clear(PyThreadState *tstate)¶ Сбрасывает всю информацию в объекте состояния потока. Глобальная блокировка интерпретатора должна удерживаться.
-
void
PyThreadState_Delete(PyThreadState *tstate)¶ Уничтожает объект состояния потока. Глобальная блокировка интерпретатора может не удерживаться. Состояние потока должно быть предварительно сброшено вызовом
PyThreadState_Clear().
-
PY_INT64_T
PyInterpreterState_GetID(PyInterpreterState *interp)¶ Возвращает уникальный идентификатор интерпретатора. Если при этом произошла ошибка, возвращается
-1и устанавливается исключение.Добавлено в версии 3.7.
-
PyObject*
PyInterpreterState_GetDict(PyInterpreterState *interp)¶ Возвращает словарь, в котором могут храниться данные, специфичные для интерпретатора. Если эта функция возвращает
NULL, исключение не было возбуждено, и вызывающий код должен считать, что словарь данных интерпретатора недоступен.Это не замена
PyModule_GetState(), который расширения должны использовать для хранения информации о состоянии интерпретатора.Новое в версии 3.8.
-
PyObject*
PyThreadState_GetDict()¶ - Возвращаемое значение: заимствованная ссылка.
Возвращает словарь, в котором расширения могут хранить информацию о состоянии, специфичном для потока. Каждое расширение должно использовать уникальный ключ для хранения состояния в словаре. Допускается вызывать эту функцию, когда нет текущего состояния потока. Если эта функция возвращает
NULL, исключение не было возбуждено, и вызывающий должен предполагать, что текущее состояние потока недоступно.
-
int
PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)¶ Асинхронно возбуждает исключение в потоке. Аргумент id – это идентификатор потока целевого потока; exc – это объект исключения, которое нужно возбудить. Эта функция не крадёт ссылки на exc. Для предотвращения наивного misuse требуется написать собственное C-расширение для её вызова. Должна вызываться с удержанием GIL. Возвращает количество изменённых состояний потока; обычно это единица, но будет нулём, если идентификатор потока не найден. Если exc равно
NULL, отложенное исключение (если есть) для потока очищается. Эта функция не возбуждает исключений.Изменено в версии 3.7: тип параметра id изменён с
longнаunsigned long.
-
void
PyEval_AcquireThread(PyThreadState *tstate)¶ Захватывает глобальную блокировку интерпретатора и устанавливает текущее состояние потока в 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)¶ Сбрасывает текущее состояние потока в
NULLи освобождает глобальную блокировку интерпретатора. Блокировка должна быть создана ранее и должна удерживаться текущим потоком. Аргумент tstate, который не должен бытьNULL, используется только для проверки, что он представляет текущее состояние потока – если это не так, выводится фатальная ошибка.PyEval_SaveThread()– функция более высокого уровня, которая всегда доступна (даже если потоки не были инициализированы).
-
void
PyEval_AcquireLock()¶ Захватывает глобальную блокировку интерпретатора. Блокировка должна быть создана заранее. Если этот поток уже удерживает блокировку, возникает взаимоблокировка.
Устарело с версии 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()¶ Освобождает глобальную блокировку интерпретатора. Блокировка должна быть создана заранее.
Устарело с версии 3.2: Эта функция не обновляет текущее состояние потока. Вместо неё используйте
PyEval_SaveThread()илиPyEval_ReleaseThread().
Поддержка под-интерпретаторов¶Sub-interpreter support
Хотя в большинстве случаев достаточно встроить один интерпретатор Python, бывают ситуации, когда требуется создать несколько независимых интерпретаторов в одном процессе и даже в одном потоке. Под-интерпретаторы позволяют это сделать.
«Главный» интерпретатор – это первый интерпретатор, создаваемый при инициализации среды выполнения.
Обычно он является единственным интерпретатором Python в процессе. В отличие от под-интерпретаторов, главный интерпретатор обладает уникальными общепроцессными обязанностями, такими как обработка сигналов. Он также отвечает за выполнение при инициализации среды выполнения и обычно является активным интерпретатором при завершении работы среды выполнения. Функция PyInterpreterState_Main() возвращает указатель на его состояние.
Переключаться между под-интерпретаторами можно с помощью функции PyThreadState_Swap().
Создавать и удалять их можно с помощью следующих функций:
-
PyThreadState*
Py_NewInterpreter()¶ Создаёт новый под-интерпретатор. Это (почти) полностью независимое окружение для выполнения кода Python. В частности, новый интерпретатор имеет отдельные, независимые версии всех импортированных модулей, включая фундаментальные модули
builtins,__main__иsys. Таблица загруженных модулей (sys.modules) и путь поиска модулей (sys.path) также отдельные. В новом окружении нет переменнойsys.argv. У него есть новые файловые объекты стандартных потоков ввода-выводаsys.stdin,sys.stdoutиsys.stderr(однако они ссылаются на те же нижележащие файловые дескрипторы).Возвращаемое значение указывает на первое состояние потока, созданное в новом под-интерпретаторе. Это состояние потока устанавливается в текущем состоянии потока. Обратите внимание, что никакой реальный поток не создаётся; см. обсуждение состояний потока ниже. Если создание нового интерпретатора оказалось неудачным, возвращается
NULL; никакое исключение не устанавливается, поскольку состояние исключения хранится в текущем состоянии потока, и текущее состояние потока может отсутствовать. (Как и во всех остальных функциях Python/C API, глобальная блокировка интерпретатора должна удерживаться перед вызовом этой функции и остаётся удерживаться при возврате; однако, в отличие от большинства других функций Python/C API, при входе не обязательно должно быть текущее состояние потока.)Модули расширения совместно используются (под-)интерпретаторами следующим образом:
Для модулей, использующих многофазную инициализацию, например
PyModule_FromDefAndSpec(), для каждого интерпретатора создаётся и инициализируется отдельный объект модуля. Между этими объектами модулей совместно используются только статические и глобальные переменные на уровне C.Для модулей, использующих однофазную инициализацию, например
PyModule_Create(), при первом импорте определённого расширения оно инициализируется обычным образом, и (поверхностная) копия его словаря модуля сохраняется. Когда то же расширение импортируется другим (под-)интерпретатором, новый модуль инициализируется и заполняется содержимым этой копии; функцияinitрасширения не вызывается. Таким образом, объекты в словаре модуля оказываются общими для (под-)интерпретаторов, что может вызывать нежелательное поведение (см. Ошибки и предостережения ниже).Обратите внимание, что это отличается от ситуации, когда расширение импортируется после полной повторной инициализации интерпретатора вызовом
Py_FinalizeEx()иPy_Initialize(); в этом случае функцияinitmoduleрасширения вызывается снова. Как и при многофазной инициализации, это означает, что между этими модулями совместно используются только статические и глобальные переменные на уровне C.
-
void
Py_EndInterpreter(PyThreadState *tstate)¶ Уничтожает (под-)интерпретатор, представленный данным состоянием потока. Данное состояние потока должно быть текущим состоянием потока. См. обсуждение состояний потока ниже. Когда вызов возвращается, текущее состояние потока равно
NULL. Все состояния потока, связанные с этим интерпретатором, уничтожаются. (Глобальная блокировка интерпретатора должна удерживаться перед вызовом этой функции и всё ещё удерживается при возврате.)Py_FinalizeEx()уничтожит все под-интерпретаторы, которые не были явно уничтожены к этому моменту.
Ошибки и предостережения¶Bugs and caveats
Поскольку под-интерпретаторы (и главный интерпретатор) являются частью одного
процесса, изоляция между ними не идеальна – например, с помощью
низкоуровневых файловых операций, таких как os.close(), они могут
(случайно или намеренно) влиять на открытые файлы друг друга. Из-за
того, как расширения совместно используются (под-)интерпретаторами, некоторые расширения могут
работать некорректно; это особенно вероятно при использовании однофазной инициализации
или (статических) глобальных переменных.
Можно вставлять объекты, созданные в одном под-интерпретаторе, в
пространство имён другого (под-)интерпретатора; этого следует избегать, если возможно.
Следует проявлять особую осторожность, чтобы избежать совместного использования пользовательских функций, методов, экземпляров или классов между под-интерпретаторами, поскольку операции импорта, выполняемые такими объектами, могут повлиять на словарь загруженных модулей не того (под-)интерпретатора. Не менее важно избегать совместного использования объектов, из которых доступны вышеперечисленные.
Также обратите внимание, что комбинирование этой функциональности с API PyGILState_*()
является деликатным, поскольку эти API предполагают взаимно однозначное соответствие между состояниями потоков Python
и потоками уровня ОС, а это предположение нарушается наличием под-интерпретаторов.
Настоятельно рекомендуется не переключать под-интерпретаторы между парой
соответствующих вызовов PyGILState_Ensure() и PyGILState_Release().
Более того, расширения (такие как ctypes), использующие эти API для вызова
кода Python из потоков, созданных не в Python, вероятно, будут работать неправильно при использовании
под-интерпретаторов.
Асинхронные уведомления¶Asynchronous Notifications
Предоставляется механизм для асинхронных уведомлений основному потоку интерпретатора. Эти уведомления имеют форму указателя на функцию и аргумента в виде указателя void.
-
int
Py_AddPendingCall(int (*func)(void *), void *arg)¶ Планирует вызов функции из основного потока интерпретатора. В случае успеха возвращается
0, и func помещается в очередь для вызова в основном потоке. В случае неудачи возвращается-1без установки какого-либо исключения.При успешной постановке в очередь func будет в конечном итоге вызвана из основного потока интерпретатора с аргументом arg. Она будет вызвана асинхронно по отношению к нормально выполняющемуся коду Python, но при соблюдении обоих этих условий:
на границе байткода;
при этом главный поток удерживает глобальную блокировку интерпретатора (поэтому func может использовать полный C API).
func должна возвращать
0при успехе или-1при неудаче с установленным исключением. func не будет прервана для рекурсивного выполнения другого асинхронного уведомления, но её всё ещё можно прервать для переключения потоков, если глобальная блокировка интерпретатора освобождена.Для выполнения этой функции не требуется текущее состояние потока, и ей не нужна глобальная блокировка интерпретатора.
Предупреждение
Это низкоуровневая функция, полезная только в особых случаях. Нет гарантии, что func будет вызвана максимально быстро. Если главный поток занят выполнением системного вызова, func не будет вызвана до возврата из системного вызова. Эта функция в целом не подходит для вызова кода Python из произвольных C-потоков. Вместо неё используйте PyGILState API.
Новое в версии 3.1.
Профилирование и трассировка¶Profiling and Tracing
Интерпретатор Python предоставляет низкоуровневую поддержку для подключения средств профилирования и трассировки выполнения. Они используются в инструментах профилирования, отладки и анализа покрытия.
Этот C-интерфейс позволяет коду профилирования или трассировки избежать накладных расходов на вызов через вызываемые объекты уровня Python, выполняя вместо этого прямой вызов C-функции. Основные характеристики механизма не изменились; интерфейс позволяет устанавливать функции трассировки для каждого потока, а базовые события, сообщаемые функции трассировки, такие же, как и в предыдущих версиях для функций трассировки уровня Python.
-
int
(*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)¶ Тип функции трассировки, регистрируемой с помощью
PyEval_SetProfile()иPyEval_SetTrace(). Первый параметр – это объект, переданный функции регистрации как obj, frame – это объект фрейма, к которому относится событие, what – одна из константPyTrace_CALL,PyTrace_EXCEPTION,PyTrace_LINE,PyTrace_RETURN,PyTrace_C_CALL,PyTrace_C_EXCEPTION,PyTrace_C_RETURNилиPyTrace_OPCODE, а arg зависит от значения what:Значение what
Смысл arg
PyTrace_CALLВсегда
Py_None.PyTrace_EXCEPTIONИнформация об исключении, возвращаемая
sys.exc_info().PyTrace_LINEВсегда
Py_None.PyTrace_RETURNЗначение, возвращаемое вызывающему коду, или
NULL, если вызвано исключением.PyTrace_C_CALLВызываемый объект функции.
PyTrace_C_EXCEPTIONВызываемый объект функции.
PyTrace_C_RETURNВызываемый объект функции.
PyTrace_OPCODEВсегда
Py_None.
-
int
PyTrace_CALL¶ Значение параметра what для функции
Py_tracefunc, когда сообщается о новом вызове функции или метода, или о новом входе в генератор. Обратите внимание, что создание итератора для функции-генератора не сообщается, поскольку в соответствующем фрейме не происходит передачи управления байт-коду Python.
-
int
PyTrace_EXCEPTION¶ Значение параметра what в функции
Py_tracefunc, когда возникло исключение. Функция колбэка вызывается с этим значением для what после обработки любого байт-кода, после которого исключение оказывается установленным в выполняемом фрейме. Эффект этого заключается в том, что по мере распространения исключения, вызывающего раскрутку стека Python, колбэк вызывается при возврате в каждый фрейм по мере распространения исключения. Только функции трассировки получают эти события; профилировщику они не нужны.
-
int
PyTrace_LINE¶ Значение, передаваемое как параметр what в функцию
Py_tracefunc(но не в функцию профилирования), когда сообщается о событии номера строки. Его можно отключить для фрейма, установивf_trace_linesв 0 на этом фрейме.
-
int
PyTrace_RETURN¶ Значение параметра what для функций
Py_tracefunc, когда вызов собирается вернуться.
-
int
PyTrace_C_CALL¶ Значение параметра what для функций
Py_tracefunc, когда собирается быть вызвана C-функция.
-
int
PyTrace_C_EXCEPTION¶ Значение параметра what для функций
Py_tracefunc, когда C-функция вызвала исключение.
-
int
PyTrace_C_RETURN¶ Значение параметра what для функций
Py_tracefunc, когда C-функция вернулась.
-
int
PyTrace_OPCODE¶ Значение параметра what для функций
Py_tracefunc(но не функций профилирования), когда собирается быть выполнен новый опкод. Это событие не генерируется по умолчанию: его нужно явно запросить, установивf_trace_opcodesв 1 во фрейме.
-
void
PyEval_SetProfile(Py_tracefunc func, PyObject *obj)¶ Устанавливает функцию профилирования в func. Параметр obj передаётся функции в качестве первого аргумента; это может быть любой объект Python или
NULL. Если функции профилирования нужно поддерживать состояние, использование разных значений obj для каждого потока предоставляет удобное и потокобезопасное место для его хранения. Функция профилирования вызывается для всех отслеживаемых событий, кромеPyTrace_LINE,PyTrace_OPCODEиPyTrace_EXCEPTION.
-
void
PyEval_SetTrace(Py_tracefunc func, PyObject *obj)¶ Устанавливает функцию трассировки в func. Это похоже на
PyEval_SetProfile(), за исключением того, что функция трассировки получает события номеров строк и события на каждую операцию, но не получает событий, связанных с вызовом объектов функций C. Любая функция трассировки, зарегистрированная черезPyEval_SetTrace(), не будет получатьPyTrace_C_CALL,PyTrace_C_EXCEPTIONилиPyTrace_C_RETURNв качестве значения параметра what.
Поддержка расширенного отладчика¶Advanced Debugger Support
Эти функции предназначены только для использования расширенными инструментами отладки.
-
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.
Поддержка локального хранилища потоков¶Thread Local Storage Support
Интерпретатор Python предоставляет низкоуровневую поддержку для локального хранилища потока (TLS), которая оборачивает нижележащую нативную реализацию TLS для поддержки API потокового локального хранилища на уровне Python (threading.local). API CPython на уровне C похожи на те, что предоставляются pthreads и Windows: используется ключ потока и функции для связывания значения void* с каждым потоком.
GIL не нужно удерживать при вызове этих функций; они обеспечивают собственную блокировку.
Обратите внимание, что Python.h не содержит объявления TLS-функций; для использования локальной памяти потока необходимо включить pythread.h.
Примечание
Ни одна из этих функций API не занимается управлением памятью для значений void*. Их необходимо выделять и освобождать самостоятельно. Если значения void* оказываются PyObject*, эти функции также не выполняют над ними операции подсчёта ссылок.
API потоково-специфичного хранилища (TSS)¶Thread Specific Storage (TSS) API
API TSS введён для замены использования существующего TLS API в интерпретаторе CPython. Этот API использует новый тип Py_tss_t вместо int для представления ключей потоков.
Добавлено в версии 3.7.
См. также
«Новый C-API для локальной памяти потока в CPython» (PEP 539)
-
Py_tss_t¶ Эта структура данных представляет состояние ключа потока; её определение может зависеть от конкретной реализации TLS, и она содержит внутреннее поле, отражающее состояние инициализации ключа. Открытых членов этой структуры нет.
Если Py_LIMITED_API не определён, допускается статическое размещение этого типа с помощью
Py_tss_NEEDS_INIT.
-
Py_tss_NEEDS_INIT¶ Этот макрос раскрывается в инициализатор для переменных типа
Py_tss_t. Обратите внимание, что этот макрос не будет определён вместе с Py_LIMITED_API.
Динамическое выделение¶Dynamic Allocation
Динамическое выделение Py_tss_t требуется в модулях расширения, собранных с Py_LIMITED_API, где статическое размещение этого типа невозможно из-за того, что его реализация скрыта во время сборки.
-
Py_tss_t*
PyThread_tss_alloc()¶ Возвращает значение, находящееся в том же состоянии, что и значение, инициализированное с помощью
Py_tss_NEEDS_INIT, илиNULLв случае ошибки динамического выделения.
-
void
PyThread_tss_free(Py_tss_t *key)¶ Освобождает указанный ключ, выделенный с помощью
PyThread_tss_alloc(), после предварительного вызоваPyThread_tss_delete(), чтобы гарантировать, что все связанные локальные переменные потоков отменены. Эта операция ничего не делает, если аргумент ключ равен NULL.Примечание
Освобождённый ключ становится висячим указателем; следует сбросить ключ в NULL.
Методы¶Methods
Параметр key этих функций не должен быть NULL. Кроме того, поведение PyThread_tss_set() и PyThread_tss_get() не определено, если заданный Py_tss_t не был инициализирован с помощью PyThread_tss_create().
-
int
PyThread_tss_is_created(Py_tss_t *key)¶ Возвращает ненулевое значение, если заданный
Py_tss_tбыл инициализирован с помощьюPyThread_tss_create().
-
int
PyThread_tss_create(Py_tss_t *key)¶ Возвращает нулевое значение при успешной инициализации TSS-ключа. Поведение не определено, если значение, на которое указывает аргумент key, не инициализировано с помощью
Py_tss_NEEDS_INIT. Эту функцию можно вызывать для одного и того же ключа многократно – вызов для уже инициализированного ключа ничего не делает и сразу возвращает успех.
-
void
PyThread_tss_delete(Py_tss_t *key)¶ Уничтожает TSS-ключ, забывая связанные с ним значения во всех потоках, и переводит состояние инициализации ключа в «не инициализирован». Уничтоженный ключ можно повторно инициализировать с помощью
PyThread_tss_create(). Эту функцию можно вызывать для одного и того же ключа многократно – вызов для уже уничтоженного ключа ничего не делает.
API локального хранилища потоков (TLS)¶Thread Local Storage (TLS) API
Устарело с версии 3.7: Этот API заменён API поток-специфичного хранилища (TSS).
Примечание
Эта версия API не поддерживает платформы, где нативный ключ TLS
определён так, что его нельзя безопасно привести к int. На таких платформах
PyThread_create_key() немедленно возвращает статус ошибки,
а остальные функции TLS на таких платформах ничего не делают.
Из-за упомянутой выше проблемы совместимости эту версию API не следует использовать в новом коде.
-
int
PyThread_create_key()¶
-
void
PyThread_delete_key(int key)¶
-
int
PyThread_set_key_value(int key, void *value)¶
-
void*
PyThread_get_key_value(int key)¶
-
void
PyThread_delete_key_value(int key)¶
-
void
PyThread_ReInitTLS()¶