Инициализация, финализация и потоки¶
См. также Python Initialization Configuration.
Перед инициализацией Python¶
В приложении, встраивающем Python, функция Py_Initialize()
должна быть вызвана перед использованием любых других функций Python/C API; за исключением нескольких функций и global configuration variables.
Следующие функции можно безопасно вызывать до инициализации Python:
Функции конфигурации:
Информационные функции:
Коммунальные услуги:
Распределители памяти:
Примечание
Следующие функции не должны вызываться перед Py_Initialize()
: Py_EncodeLocale()
, Py_GetPath()
, Py_GetPrefix()
, Py_GetExecPrefix()
, Py_GetProgramFullPath()
, Py_GetPythonHome()
, Py_GetProgramName()
и PyEval_InitThreads()
.
Глобальные переменные конфигурации¶
В Python есть переменные глобальной конфигурации для управления различными функциями и опциями. По умолчанию этими флагами управляет command line options.
Когда флаг устанавливается опцией, значение флага равно количеству раз, когда опция была установлена. Например, -b
устанавливает Py_BytesWarningFlag
в 1, а -bb
устанавливает Py_BytesWarningFlag
в 2.
-
int
Py_BytesWarningFlag
¶ Выдавать предупреждение при сравнении
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
кодировкуreplace
вместо кодировки UTF-8 с обработчиком ошибокsurrogatepass
для filesystem encoding and error handler.Устанавливается в
1
, если переменная окруженияPYTHONLEGACYWINDOWSFSENCODING
установлена в непустую строку.Более подробную информацию см. в разделе PEP 529.
Availability: Windows.
-
int
Py_LegacyWindowsStdioFlag
¶ Если флаг ненулевой, используйте
io.FileIO
вместоWindowsConsoleIO
для стандартных потоковsys
.Устанавливается в
1
, если переменная окруженияPYTHONLEGACYWINDOWSSTDIO
установлена в непустую строку.Более подробную информацию см. в разделе PEP 528.
Availability: 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
()¶ - Part of the Stable ABI.
Инициализация интерпретатора 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
, что также повлияет на не-Python использование консоли с помощью C Runtime.
-
void
Py_InitializeEx
(int initsigs)¶ - Part of the Stable ABI.
Эта функция работает как
Py_Initialize()
, если initsigs равно1
. Если initsigs равно0
, то она пропускает инициализационную регистрацию обработчиков сигналов, что может быть полезно при встраивании Python.
-
int
Py_IsInitialized
()¶ - Part of the Stable ABI.
Возвращает true (ненулевое значение), если интерпретатор Python был инициализирован, false (нулевое значение), если нет. После вызова
Py_FinalizeEx()
возвращается false, покаPy_Initialize()
не будет вызван снова.
-
int
Py_FinalizeEx
()¶ - Part of the Stable ABI since version 3.6.
Отмените все инициализации, сделанные
Py_Initialize()
и последующее использование функций Python/C API, и уничтожьте все подинтерпретаторы (см.Py_NewInterpreter()
ниже), которые были созданы и еще не уничтожены после последнего вызоваPy_Initialize()
. В идеале, при этом освобождается вся память, выделенная интерпретатору Python. При повторном вызове (без предварительного вызоваPy_Initialize()
) эта функция не работает. Обычно возвращаемое значение0
. Если при финализации (очистке буферизованных данных) возникли ошибки, возвращается-1
.Эта функция предоставляется по нескольким причинам. Встраиваемое приложение может захотеть перезапустить Python без необходимости перезапуска самого приложения. Приложение, загрузившее интерпретатор Python из динамически загружаемой библиотеки (или DLL), может захотеть освободить всю память, выделенную Python, перед выгрузкой DLL. Во время поиска утечек памяти в приложении разработчик может захотеть освободить всю память, выделенную Python, перед выходом из приложения.
Ошибки и предостережения: Уничтожение модулей и объектов в модулях происходит в случайном порядке; это может привести к сбою деструкторов (методов
__del__()
), если они зависят от других объектов (даже функций) или модулей. Динамически загруженные модули расширения, загруженные Python, не выгружаются. Небольшие объемы памяти, выделенные интерпретатором Python, могут не освобождаться (если вы обнаружили утечку, пожалуйста, сообщите об этом). Память, связанная круговыми ссылками между объектами, не освобождается. Некоторая память, выделенная модулями расширения, может быть не освобождена. Некоторые расширения могут работать некорректно, если их процедура инициализации вызывается более одного раза; это может произойти, если приложение вызываетPy_Initialize()
иPy_FinalizeEx()
более одного раза.Вызывает auditing event
cpython._PySys_ClearAuditHooks
без аргументов.Добавлено в версии 3.6.
-
void
Py_Finalize
()¶ - Part of the Stable ABI.
Это обратно совместимая версия
Py_FinalizeEx()
, которая не учитывает возвращаемое значение.
Параметры всего процесса¶
-
int
Py_SetStandardStreamEncoding
(const char *encoding, const char *errors)¶ Эта функция должна быть вызвана до
Py_Initialize()
, если она вообще вызывается. Она определяет, какую кодировку и обработку ошибок использовать со стандартным IO, с теми же значениями, что и вstr.encode()
.Она переопределяет значения
PYTHONIOENCODING
и позволяет встраивать код для управления кодировкой ввода-вывода, когда переменная окружения не работает.encoding и/или errors могут
NULL
использоватьPYTHONIOENCODING
и/или значения по умолчанию (в зависимости от других настроек).Обратите внимание, что
sys.stderr
всегда использует обработчик ошибок «backslashreplace», независимо от этой (или любой другой) настройки.Если вызывается
Py_FinalizeEx()
, то эту функцию нужно будет вызвать снова, чтобы повлиять на последующие вызовыPy_Initialize()
.Возвращает
0
в случае успеха, ненулевое значение при ошибке (например, вызов после того, как интерпретатор уже был инициализирован).Добавлено в версии 3.4.
-
void
Py_SetProgramName
(const wchar_t *name)¶ - Part of the Stable ABI.
Эта функция должна быть вызвана перед первым вызовом
Py_Initialize()
, если она вообще вызывается. Она сообщает интерпретатору значение аргументаargv[0]
к функцииmain()
программы (преобразованное в широкие символы). Это значение используетсяPy_GetPath()
и некоторыми другими функциями ниже для поиска библиотек времени выполнения Python относительно исполняемого файла интерпретатора. По умолчанию используется значение'python'
. Аргумент должен указывать на широкую символьную строку с нулевым окончанием в статическом хранилище, содержимое которой не будет меняться в течение всего времени выполнения программы. Никакой код в интерпретаторе Python не будет изменять содержимое этого хранилища.Используйте
Py_DecodeLocale()
для декодирования байтовой строки, чтобы получить строку wchar_*.
-
wchar *
Py_GetProgramName
()¶ - Part of the Stable ABI.
Возвращает имя программы, заданное с помощью
Py_SetProgramName()
, или значение по умолчанию. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение.Эта функция не должна вызываться до
Py_Initialize()
, иначе она возвращаетNULL
.Изменено в версии 3.10: Теперь она возвращает
NULL
, если вызвана доPy_Initialize()
.
-
wchar_t *
Py_GetPrefix
()¶ - Part of the Stable 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
()¶ - Part of the Stable ABI.
Возвращает exec-prefix для установленных платформенно-зависимых файлов. Он определяется по ряду сложных правил из имени программы, заданного с помощью
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-prefix не имеют смысла и устанавливаются в пустую строку. Обратите внимание, что скомпилированные файлы байткода Python независимы от платформы (но не независимы от версии Python, под которую они были скомпилированы!).
Системные администраторы будут знать, как настроить программы mount или automount для совместного использования
/usr/local
между платформами, при этом/usr/local/plat
будет отдельной файловой системой для каждой платформы.Эта функция не должна вызываться до
Py_Initialize()
, иначе она возвращаетNULL
.Изменено в версии 3.10: Теперь она возвращает
NULL
, если вызвана доPy_Initialize()
.
-
wchar_t *
Py_GetProgramFullPath
()¶ - Part of the Stable ABI.
Возвращает полное имя программы исполняемого файла Python; оно вычисляется как побочный эффект выведения пути поиска модуля по умолчанию из имени программы (заданного
Py_SetProgramName()
выше). Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python какsys.executable
.Эта функция не должна вызываться до
Py_Initialize()
, иначе она возвращаетNULL
.Изменено в версии 3.10: Теперь она возвращает
NULL
, если вызвана доPy_Initialize()
.
-
wchar_t *
Py_GetPath
()¶ - Part of the Stable ABI.
Возвращает путь поиска модуля по умолчанию; он вычисляется из имени программы (заданного выше
Py_SetProgramName()
) и некоторых переменных окружения. Возвращаемая строка состоит из серии имен каталогов, разделенных разделительным символом, зависящим от платформы. Символ разделителя -':'
в Unix и macOS,';'
в Windows. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Списокsys.path
инициализируется этим значением при запуске интерпретатора; позже его можно (и обычно так и происходит) изменить, чтобы изменить путь поиска для загрузки модулей.Эта функция не должна вызываться до
Py_Initialize()
, иначе она возвращаетNULL
.Изменено в версии 3.10: Теперь она возвращает
NULL
, если вызвана доPy_Initialize()
.
-
void
Py_SetPath
(const wchar_t*)¶ - Part of the Stable ABI since version 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
()¶ - Part of the Stable 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
()¶ - Part of the Stable ABI.
Возвращает идентификатор платформы для текущей платформы. В Unix он формируется из «официального» названия операционной системы, преобразованного в нижний регистр, за которым следует номер основной ревизии; например, для Solaris 2.x, который также известен как SunOS 5.x, значение
'sunos5'
. Для macOS это'darwin'
. В Windows это значение равно'win'
. Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python какsys.platform
.
-
const char *
Py_GetCopyright
()¶ - Part of the Stable ABI.
Возвращает официальную строку авторского права для текущей версии Python, например
'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'
Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как
sys.copyright
.
-
const char *
Py_GetCompiler
()¶ - Part of the Stable ABI.
Возвращает указание на компилятор, использованный для сборки текущей версии Python, в квадратных скобках, например:
"[GCC 2.7.2.2]"
Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как часть переменной
sys.version
.
-
const char *
Py_GetBuildInfo
()¶ - Part of the Stable ABI.
Возвращает информацию о порядковом номере и дате и времени сборки текущего экземпляра интерпретатора Python, например
"#67, Aug 1 1997, 22:34:28"
Возвращаемая строка указывает на статическое хранилище; вызывающая сторона не должна изменять ее значение. Значение доступно для кода Python как часть переменной
sys.version
.
-
void
PySys_SetArgvEx
(int argc, wchar_t **argv, int updatepath)¶ - Part of the Stable 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)¶ - Part of the Stable ABI.
Эта функция работает как
PySys_SetArgvEx()
с updatepath, установленным в1
, если только интерпретатор python не был запущен с помощью-I
.Используйте
Py_DecodeLocale()
для декодирования байтовой строки, чтобы получить строку wchar_*.Изменено в версии 3.4: Значение updatepath зависит от
-I
.
-
void
Py_SetPythonHome
(const wchar_t *home)¶ - Part of the Stable ABI.
Устанавливает «домашний» каталог по умолчанию, то есть расположение стандартных библиотек Python. Значение строки аргумента см. в
PYTHONHOME
.Аргумент должен указывать на строку символов с нулевым окончанием в статическом хранилище, содержимое которого не будет меняться в течение всего времени выполнения программы. Никакой код в интерпретаторе Python не изменит содержимое этого хранилища.
Используйте
Py_DecodeLocale()
для декодирования байтовой строки, чтобы получить строку wchar_*.
-
w_char *
Py_GetPythonHome
()¶ - Part of the Stable ABI.
Возвращает «дом» по умолчанию, то есть значение, установленное предыдущим вызовом
Py_SetPythonHome()
, или значение переменной окруженияPYTHONHOME
, если она установлена.Эта функция не должна вызываться до
Py_Initialize()
, иначе она возвращаетNULL
.Изменено в версии 3.10: Теперь она возвращает
NULL
, если вызвана доPy_Initialize()
.
Состояние потоков и блокировка глобального интерпретатора¶
Интерпретатор Python не является полностью потокобезопасным. Для поддержки многопоточных программ Python существует глобальная блокировка, называемая global interpreter lock или GIL, которая должна быть у текущего потока, прежде чем он сможет безопасно получить доступ к объектам Python. Без блокировки даже самые простые операции могут вызвать проблемы в многопоточной программе: например, когда два потока одновременно увеличивают количество ссылок на один и тот же объект, количество ссылок может быть увеличено только один раз вместо двух.
Поэтому существует правило, что только тот поток, который получил GIL, может работать с объектами Python или вызывать функции Python/C API. Чтобы эмулировать параллельность выполнения, интерпретатор регулярно пытается переключать потоки (см. sys.setswitchinterval()
). Блокировка также снимается во время потенциально блокирующих операций ввода-вывода, таких как чтение или запись файла, чтобы другие потоки Python могли в это время работать.
Интерпретатор Python хранит некоторую информацию о потоках в структуре данных под названием PyThreadState
. Существует также одна глобальная переменная, указывающая на текущую PyThreadState
: ее можно получить с помощью PyThreadState_Get()
.
Освобождение GIL от кода расширения¶
Большинство кода расширения, манипулирующего GIL, имеет следующую простую структуру:
Save the thread state in a local variable.
Release the global interpreter lock.
... Do some blocking I/O operation ...
Reacquire the global interpreter lock.
Restore the thread state from the local variable.
Это настолько частое явление, что для его упрощения существует пара макросов:
Py_BEGIN_ALLOW_THREADS
... Do some blocking I/O operation ...
Py_END_ALLOW_THREADS
Макрос Py_BEGIN_ALLOW_THREADS
открывает новый блок и объявляет скрытую локальную переменную; макрос Py_END_ALLOW_THREADS
закрывает блок.
Блок выше расширяется до следующего кода:
PyThreadState *_save;
_save = PyEval_SaveThread();
... Do some blocking I/O operation ...
PyEval_RestoreThread(_save);
Вот как работают эти функции: глобальная блокировка интерпретатора используется для защиты указателя на текущее состояние потока. При освобождении блокировки и сохранении состояния потока указатель текущего состояния потока должен быть получен до освобождения блокировки (поскольку другой поток может немедленно получить блокировку и сохранить свое состояние потока в глобальной переменной). И наоборот, при приобретении блокировки и восстановлении состояния потока блокировка должна быть приобретена до сохранения указателя состояния потока.
Примечание
Вызов системных функций ввода-вывода является наиболее распространенным случаем использования освобождения GIL, но это также может быть полезно перед вызовом длительных вычислений, которые не требуют доступа к объектам Python, например, сжатия или криптографических функций, работающих с буферами памяти. Например, стандартные модули zlib
и hashlib
освобождают GIL при сжатии или хэшировании данных.
Потоки, созданные не на языке Python¶
Когда потоки создаются с помощью специальных API Python (например, модуля threading
), состояние потока автоматически ассоциируется с ними, поэтому приведенный выше код корректен. Однако когда потоки создаются из языка C (например, с помощью сторонней библиотеки с собственным управлением потоками), они не хранят GIL, и для них не существует структуры состояния потока.
Если вам нужно вызвать код Python из этих потоков (часто это является частью API обратного вызова, предоставляемого вышеупомянутой сторонней библиотекой), вы должны сначала зарегистрировать эти потоки в интерпретаторе, создав структуру данных состояния потока, затем получить GIL и, наконец, сохранить указатель состояния потока, прежде чем вы сможете начать использовать API Python/C. Когда вы закончите, вы должны сбросить указатель состояния потока, освободить GIL и, наконец, освободить структуру данных состояния потока.
Функции PyGILState_Ensure()
и PyGILState_Release()
делают все вышеперечисленное автоматически. Типичная идиома для вызова в Python из потока C такова:
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
/* Perform Python actions here. */
result = CallSomeFunction();
/* evaluate result or handle exception */
/* Release the thread. No Python API allowed beyond this point. */
PyGILState_Release(gstate);
Обратите внимание, что функции PyGILState_* предполагают наличие только одного глобального интерпретатора (создаваемого автоматически с помощью Py_Initialize()
). Python поддерживает создание дополнительных интерпретаторов (с помощью Py_NewInterpreter()
), но смешивание нескольких интерпретаторов и API PyGILState_* не поддерживается.
Предостережения по поводу fork()¶
Еще одна важная вещь, которую следует отметить о потоках, это их поведение перед лицом вызова C fork()
. В большинстве систем с fork()
, после форка процесса будет существовать только тот поток, который выдал форк. Это имеет конкретное влияние как на то, как должны обрабатываться блокировки, так и на все хранимое состояние во времени выполнения CPython.
Тот факт, что остается только «текущий» поток, означает, что все блокировки, удерживаемые другими потоками, никогда не будут освобождены. Python решает эту проблему для os.fork()
, приобретая внутренние блокировки, которые он использует до развилки, и освобождая их после. Кроме того, он сбрасывает все Блокировка объектов в дочернем потоке. При расширении или встраивании Python нет способа сообщить Python о дополнительных (непитоновских) блокировках, которые необходимо получить до или сбросить после развилки. Для этого необходимо использовать средства ОС, такие как pthread_atfork()
. Кроме того, при расширении или встраивании Python вызов fork()
напрямую, а не через os.fork()
(и возврат или вызов в Python) может привести к тупику из-за того, что одна из внутренних блокировок Python удерживается потоком, который прекратил свое существование после развилки. PyOS_AfterFork_Child()
пытается сбросить необходимые блокировки, но не всегда может это сделать.
Тот факт, что все другие потоки уходят, также означает, что состояние времени выполнения CPython должно быть очищено должным образом, что и делает os.fork()
. Это означает финализацию всех других объектов PyThreadState
, принадлежащих текущему интерпретатору, и всех других объектов PyInterpreterState
. Из-за этого и особой природы «main» interpreter, fork()
следует вызывать только в «главном» потоке интерпретатора, где изначально была инициализирована глобальная среда выполнения CPython. Единственное исключение - если exec()
будет вызван сразу после него.
API высокого уровня¶
Это наиболее часто используемые типы и функции при написании кода расширения C или при встраивании интерпретатора Python:
-
type
PyInterpreterState
¶ - Part of the Limited API (as an opaque struct).
Эта структура данных представляет состояние, разделяемое несколькими взаимодействующими потоками. Потоки, принадлежащие одному интерпретатору, совместно используют управление модулем и некоторые другие внутренние элементы. В этой структуре нет открытых членов.
Нити, принадлежащие разным интерпретаторам, изначально не имеют ничего общего, кроме состояния процесса, такого как доступная память, открытые дескрипторы файлов и тому подобное. Глобальная блокировка интерпретатора также является общей для всех потоков, независимо от того, к какому интерпретатору они принадлежат.
-
type
PyThreadState
¶ - Part of the Limited API (as an opaque struct).
Эта структура данных представляет состояние одного потока. Единственным открытым членом данных является
interp
(PyInterpreterState*), который указывает на состояние интерпретатора этого потока.
-
void
PyEval_InitThreads
()¶ - Part of the Stable ABI.
Устаревшая функция, которая ничего не делает.
В Python 3.6 и старше эта функция создавала GIL, если он не существовал.
Изменено в версии 3.9: Теперь функция ничего не делает.
Изменено в версии 3.7: Эта функция теперь вызывается
Py_Initialize()
, поэтому вам больше не нужно вызывать ее самостоятельно.Изменено в версии 3.2: Эта функция больше не может быть вызвана перед
Py_Initialize()
.Deprecated since version 3.9, will be removed in version 3.11.
-
int
PyEval_ThreadsInitialized
()¶ - Part of the Stable ABI.
Возвращает ненулевое значение, если была вызвана функция
PyEval_InitThreads()
. Эта функция может быть вызвана без удержания GIL, и поэтому может быть использована для избежания обращений к API блокировки при однопоточном выполнении.Изменено в версии 3.7: Теперь GIL инициализируется
Py_Initialize()
.Deprecated since version 3.9, will be removed in version 3.11.
-
PyThreadState *
PyEval_SaveThread
()¶ - Part of the Stable ABI.
Освободить глобальную блокировку интерпретатора (если она была создана) и сбросить состояние потока на
NULL
, возвращая предыдущее состояние потока (которое не являетсяNULL
). Если блокировка была создана, то текущий поток должен был ее получить.
-
void
PyEval_RestoreThread
(PyThreadState *tstate)¶ - Part of the Stable ABI.
Приобрести глобальную блокировку интерпретатора (если она была создана) и установить состояние потока в tstate, которое не должно быть
NULL
. Если блокировка была создана, текущий поток не должен ее получить, иначе возникнет тупик.Примечание
Вызов этой функции из потока в момент завершения работы интерпретатора приведет к завершению потока, даже если поток не был создан Python. Вы можете использовать
_Py_IsFinalizing()
илиsys.is_finalizing()
, чтобы проверить, находится ли интерпретатор в процессе завершения перед вызовом этой функции, чтобы избежать нежелательного завершения.
-
PyThreadState *
PyThreadState_Get
()¶ - Part of the Stable ABI.
Возвращает текущее состояние потока. Глобальная блокировка интерпретатора должна быть удержана. Если текущее состояние потока равно
NULL
, то выдается фатальная ошибка (чтобы вызывающая сторона не проверяла наличиеNULL
).
-
PyThreadState *
PyThreadState_Swap
(PyThreadState *tstate)¶ - Part of the Stable ABI.
Поменяйте текущее состояние потока на состояние потока, заданное аргументом tstate, который может быть
NULL
. Глобальная блокировка интерпретатора должна удерживаться и не снимается.
Следующие функции используют локальное хранение потоков и не совместимы с суб-интерпретаторами:
-
PyGILState_STATE
PyGILState_Ensure
()¶ - Part of the Stable ABI.
Убедитесь, что текущий поток готов вызвать Python C API независимо от текущего состояния Python или глобальной блокировки интерпретатора. Эта функция может быть вызвана столько раз, сколько захочет поток, если каждый вызов сопровождается вызовом
PyGILState_Release()
. В общем случае, между вызовамиPyGILState_Ensure()
иPyGILState_Release()
можно использовать другие API, связанные с потоком, при условии, что состояние потока будет восстановлено до состояния, предшествующего вызову Release(). Например, допустимо обычное использование макросовPy_BEGIN_ALLOW_THREADS
иPy_END_ALLOW_THREADS
.Возвращаемое значение - это непрозрачный «хэндл» состояния потока, когда был вызван
PyGILState_Ensure()
, который должен быть передан вPyGILState_Release()
, чтобы гарантировать, что Python останется в том же состоянии. Несмотря на то, что рекурсивные вызовы разрешены, эти дескрипторы не могут быть общими - каждый уникальный вызовPyGILState_Ensure()
должен сохранить дескриптор для своего вызоваPyGILState_Release()
.Когда функция вернется, текущий поток будет владеть GIL и сможет вызывать произвольный код Python. Отказ является фатальной ошибкой.
Примечание
Вызов этой функции из потока в момент завершения работы интерпретатора приведет к завершению потока, даже если поток не был создан Python. Вы можете использовать
_Py_IsFinalizing()
илиsys.is_finalizing()
, чтобы проверить, находится ли интерпретатор в процессе завершения перед вызовом этой функции, чтобы избежать нежелательного завершения.
-
void
PyGILState_Release
(PyGILState_STATE)¶ - Part of the Stable ABI.
Освободить все ранее полученные ресурсы. После этого вызова состояние Python будет таким же, каким оно было до соответствующего вызова
PyGILState_Ensure()
(но обычно это состояние неизвестно вызывающей стороне, поэтому используется API GILState).Каждому вызову
PyGILState_Ensure()
должен соответствовать вызовPyGILState_Release()
в том же потоке.
-
PyThreadState *
PyGILState_GetThisThreadState
()¶ - Part of the Stable ABI.
Получить текущее состояние потока для данного потока. Может вернуть
NULL
, если для текущего потока не был использован API GILState. Обратите внимание, что главный поток всегда имеет такое состояние потока, даже если в главном потоке не был сделан вызов автосостояния потока. Это в основном вспомогательная/диагностическая функция.
-
int
PyGILState_Check
()¶ Возвращает
1
, если текущий поток удерживает GIL, и0
в противном случае. Эта функция может быть вызвана из любого потока в любое время. Только если у него было инициализировано состояние потока Python и в данный момент он удерживает GIL, он вернет1
. Это в основном вспомогательная/диагностическая функция. Она может быть полезна, например, в контекстах обратного вызова или функциях распределения памяти, когда знание того, что GIL заблокирован, может позволить вызывающей стороне выполнять чувствительные действия или вести себя по-другому.Добавлено в версии 3.4.
Следующие макросы обычно используются без точки с запятой; пример использования можно найти в исходном дистрибутиве Python.
-
Py_BEGIN_ALLOW_THREADS
¶ - Part of the Stable ABI.
Этот макрос расширяется до
{ PyThreadState *_save; _save = PyEval_SaveThread();
. Обратите внимание, что он содержит открывающую скобку; он должен быть сопоставлен со следующим макросомPy_END_ALLOW_THREADS
. Дальнейшее обсуждение этого макроса см. выше.
-
Py_END_ALLOW_THREADS
¶ - Part of the Stable ABI.
Этот макрос расширяется до
PyEval_RestoreThread(_save); }
. Обратите внимание, что он содержит закрывающую скобку; он должен быть сопоставлен с более ранним макросомPy_BEGIN_ALLOW_THREADS
. Дальнейшее обсуждение этого макроса см. выше.
-
Py_BLOCK_THREADS
¶ - Part of the Stable ABI.
Этот макрос расширяется до
PyEval_RestoreThread(_save);
: он эквивалентенPy_END_ALLOW_THREADS
без закрывающей скобки.
-
Py_UNBLOCK_THREADS
¶ - Part of the Stable ABI.
Этот макрос расширяется до
_save = PyEval_SaveThread();
: он эквивалентенPy_BEGIN_ALLOW_THREADS
без открывающей скобки и объявления переменной.
Низкоуровневый API¶
Все следующие функции должны быть вызваны после Py_Initialize()
.
Изменено в версии 3.7: Py_Initialize()
теперь инициализирует GIL.
-
PyInterpreterState *
PyInterpreterState_New
()¶ - Part of the Stable ABI.
Создайте новый объект состояния интерпретатора. Глобальная блокировка интерпретатора не обязательно должна удерживаться, но может быть удержана, если необходимо сериализовать вызовы этой функции.
Вызывает auditing event
cpython.PyInterpreterState_New
без аргументов.
-
void
PyInterpreterState_Clear
(PyInterpreterState *interp)¶ - Part of the Stable ABI.
Сброс всей информации в объекте состояния интерпретатора. Глобальная блокировка интерпретатора должна быть сохранена.
Вызывает auditing event
cpython.PyInterpreterState_Clear
без аргументов.
-
void
PyInterpreterState_Delete
(PyInterpreterState *interp)¶ - Part of the Stable ABI.
Уничтожить объект состояния интерпретатора. Глобальная блокировка интерпретатора не должна удерживаться. Состояние интерпретатора должно быть сброшено предыдущим вызовом
PyInterpreterState_Clear()
.
-
PyThreadState *
PyThreadState_New
(PyInterpreterState *interp)¶ - Part of the Stable ABI.
Создает новый объект состояния потока, принадлежащий данному объекту интерпретатора. Глобальная блокировка интерпретатора не обязательно должна удерживаться, но может быть удержана, если это необходимо для сериализации вызовов этой функции.
-
void
PyThreadState_Clear
(PyThreadState *tstate)¶ - Part of the Stable ABI.
Сброс всей информации в объекте состояния потока. Глобальная блокировка интерпретатора должна быть удержана.
Изменено в версии 3.9: Эта функция теперь вызывает обратный вызов
PyThreadState.on_delete
. Ранее это происходило вPyThreadState_Delete()
.
-
void
PyThreadState_Delete
(PyThreadState *tstate)¶ - Part of the Stable ABI.
Уничтожить объект состояния потока. Глобальная блокировка интерпретатора не должна удерживаться. Состояние потока должно быть сброшено предыдущим вызовом
PyThreadState_Clear()
.
-
void
PyThreadState_DeleteCurrent
(void)¶ Уничтожить текущее состояние потока и снять глобальную блокировку интерпретатора. Как и в случае с
PyThreadState_Delete()
, глобальная блокировка интерпретатора не обязательно должна удерживаться. Состояние потока должно быть сброшено предыдущим вызовомPyThreadState_Clear()
.
-
PyFrameObject *
PyThreadState_GetFrame
(PyThreadState *tstate)¶ - Part of the Stable ABI since version 3.10.
Получить текущий кадр состояния потока Python tstate.
Возвращает strong reference. Возвращает
NULL
, если в данный момент не выполняется ни один кадр.См. также
PyEval_GetFrame()
.tstate не должно быть
NULL
.Добавлено в версии 3.9.
-
uint64_t
PyThreadState_GetID
(PyThreadState *tstate)¶ - Part of the Stable ABI since version 3.10.
Получите уникальный идентификатор состояния потока Python tstate.
tstate не должно быть
NULL
.Добавлено в версии 3.9.
-
PyInterpreterState *
PyThreadState_GetInterpreter
(PyThreadState *tstate)¶ - Part of the Stable ABI since version 3.10.
Получить интерпретатор состояния потока Python tstate.
tstate не должно быть
NULL
.Добавлено в версии 3.9.
-
PyInterpreterState *
PyInterpreterState_Get
(void)¶ - Part of the Stable ABI since version 3.9.
Получить текущий интерпретатор.
Выдает фатальную ошибку, если нет текущего состояния потока Python или нет текущего интерпретатора. Он не может возвращать NULL.
Вызывающий должен удерживать GIL.
Добавлено в версии 3.9.
-
int64_t
PyInterpreterState_GetID
(PyInterpreterState *interp)¶ - Part of the Stable ABI since version 3.7.
Возвращает уникальный идентификатор интерпретатора. Если при этом была допущена ошибка, то возвращается
-1
и устанавливается ошибка.Вызывающий должен удерживать GIL.
Добавлено в версии 3.7.
-
PyObject *
PyInterpreterState_GetDict
(PyInterpreterState *interp)¶ - Part of the Stable ABI since version 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
()¶ - Return value: Borrowed reference. Part of the Stable ABI.
Возвращает словарь, в котором расширения могут хранить информацию о состоянии конкретного потока. Каждое расширение должно использовать уникальный ключ для хранения информации о состоянии в словаре. Эту функцию можно вызывать, если текущее состояние потока недоступно. Если эта функция возвращает
NULL
, то исключение не было вызвано, и вызывающий должен считать, что текущее состояние потока недоступно.
-
int
PyThreadState_SetAsyncExc
(unsigned long id, PyObject *exc)¶ - Part of the Stable ABI.
Асинхронно вызвать исключение в потоке. Аргумент id - это идентификатор целевого потока; exc - это объект исключения, который должен быть поднят. Эта функция не крадет никаких ссылок на exc. Чтобы предотвратить наивное злоупотребление, вы должны написать собственное расширение C для вызова этой функции. Должна вызываться с установленным GIL. Возвращает количество измененных состояний потока; обычно это единица, но если идентификатор потока не найден, то будет ноль. Если exc равен
NULL
, то ожидающее исключение (если таковое имеется) для потока удаляется. Это не вызывает никаких исключений.Изменено в версии 3.7: Тип параметра id изменился с long на unsigned long.
-
void
PyEval_AcquireThread
(PyThreadState *tstate)¶ - Part of the Stable 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)¶ - Part of the Stable ABI.
Сбросьте состояние текущего потока на
NULL
и освободите глобальную блокировку интерпретатора. Блокировка должна быть создана ранее и должна принадлежать текущему потоку. Аргумент tstate, который не должен бытьNULL
, используется только для проверки того, что он представляет текущее состояние потока - если это не так, будет сообщено о фатальной ошибке.PyEval_SaveThread()
- это функция более высокого уровня, которая всегда доступна (даже когда потоки не инициализированы).
-
void
PyEval_AcquireLock
()¶ - Part of the Stable 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
()¶ - Part of the Stable ABI.
Освободите глобальную блокировку интерпретатора. Блокировка должна быть создана ранее.
Не рекомендуется, начиная с версии 3.2: Эта функция не обновляет текущее состояние потока. Вместо нее используйте
PyEval_SaveThread()
илиPyEval_ReleaseThread()
.
Поддержка суб-интерпретаторов¶
Хотя в большинстве случаев вы будете использовать только один интерпретатор Python, бывают случаи, когда вам необходимо создать несколько независимых интерпретаторов в одном процессе и, возможно, даже в одном потоке. Вложенные интерпретаторы позволяют это сделать.
Интерпретатор «main» создается первым при инициализации среды выполнения. Обычно он является единственным интерпретатором Python в процессе. В отличие от вложенных интерпретаторов, главный интерпретатор имеет уникальные глобальные для процесса обязанности, такие как обработка сигналов. Он также отвечает за выполнение во время инициализации среды выполнения и обычно является активным интерпретатором во время финализации среды выполнения. Функция PyInterpreterState_Main()
возвращает указатель на его состояние.
Вы можете переключаться между суб-интерпретаторами с помощью функции PyThreadState_Swap()
. Создавать и уничтожать их можно с помощью следующих функций:
-
PyThreadState *
Py_NewInterpreter
()¶ - Part of the Stable ABI.
Создайте новый суб-интерпретатор. Это (почти) полностью отдельная среда для выполнения кода 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
не вызывается. Таким образом, объекты в словаре модуля оказываются общими для всех (суб-)интерпретаторов, что может привести к нежелательному поведению (см. Bugs and caveats ниже).Обратите внимание, что это отличается от того, что происходит, когда расширение импортируется после того, как интерпретатор был полностью переинициализирован вызовом
Py_FinalizeEx()
иPy_Initialize()
; в этом случае функция расширенияinitmodule
*вызывается снова. Как и в случае с многофазной инициализацией, это означает, что между этими модулями совместно используются только статические и глобальные переменные уровня C.
-
void
Py_EndInterpreter
(PyThreadState *tstate)¶ - Part of the Stable ABI.
Уничтожить (под)интерпретатор, представленный заданным состоянием потока. Данное состояние потока должно быть текущим состоянием потока. См. обсуждение состояний потоков ниже. Когда вызов возвращается, текущее состояние потока равно
NULL
. Все состояния потоков, связанные с этим интерпретатором, уничтожаются. (Глобальная блокировка интерпретатора должна быть установлена до вызова этой функции и сохраняется после возврата).Py_FinalizeEx()
уничтожит все подинтерпретаторы, которые не были явно уничтожены в этот момент.
Ошибки и предостережения¶
Поскольку суб-интерпретаторы (и основной интерпретатор) являются частью одного процесса, изоляция между ними не идеальна — например, используя низкоуровневые файловые операции типа os.close()
, они могут (случайно или злонамеренно) влиять на открытые файлы друг друга. Из-за того, как расширения разделяются между (под-)интерпретаторами, некоторые расширения могут работать неправильно; это особенно вероятно при использовании однофазной инициализации или (статических) глобальных переменных. Возможна вставка объектов, созданных в одном суб-интерпретаторе, в пространство имен другого (суб-)интерпретатора; по возможности этого следует избегать.
Особое внимание следует уделять тому, чтобы избежать совместного использования определяемых пользователем функций, методов, экземпляров или классов между суб-интерпретаторами, поскольку операции импорта, выполняемые такими объектами, могут повлиять на словарь загруженных модулей неправильного (суб-)интерпретатора. Не менее важно избегать совместного использования объектов, из которых можно получить вышеперечисленное.
Также обратите внимание, что сочетание этой функциональности с API PyGILState_* является деликатным, поскольку эти API предполагают биекцию между состояниями потоков Python и потоками на уровне ОС, а это предположение нарушается наличием подынтерпретаторов. Настоятельно рекомендуется не переключать подынтерпретаторы между парой совпадающих вызовов PyGILState_Ensure()
и PyGILState_Release()
. Более того, расширения (такие как ctypes
), использующие эти API для обеспечения вызова Python-кода из потоков, созданных не на Python, вероятно, будут нарушены при использовании подынтерпретаторов.
Асинхронные уведомления¶
Предусмотрен механизм для асинхронных уведомлений основного потока интерпретатора. Эти уведомления принимают форму указателя на функцию и аргумента указателя на пустоту.
-
int
Py_AddPendingCall
(int (*func)(void*), void *arg, )¶ - Part of the Stable ABI.
Запланировать вызов функции из главного потока интерпретатора. При успехе возвращается
0
и func ставится в очередь на вызов в главном потоке. При неудаче возвращается-1
без установки какого-либо исключения.После успешной постановки в очередь func будет в конечном счете вызван из основного потока интерпретатора с аргументом arg. Она будет вызвана асинхронно по отношению к обычно выполняющемуся коду Python, но при соблюдении обоих этих условий:
на границе bytecode;
с основным потоком, удерживающим global interpreter lock (поэтому func может использовать полный C API).
func должен возвращать
0
при успехе, или-1
при неудаче с установленным исключением. func не будет прерван для выполнения другого асинхронного уведомления рекурсивно, но он все еще может быть прерван для переключения потоков, если глобальная блокировка интерпретатора освобождена.Для работы этой функции не требуется текущее состояние потока, и ей не нужна глобальная блокировка интерпретатора.
Чтобы вызвать эту функцию в подынтерпретаторе, вызывающая сторона должна владеть GIL. В противном случае функция func может быть запланирована для вызова из неправильного интерпретатора.
Предупреждение
Это низкоуровневая функция, полезная только в особых случаях. Нет никакой гарантии, что func будет вызвана как можно быстрее. Если основной поток занят выполнением системного вызова, func не будет вызвана до возвращения системного вызова. Эта функция в целом не подходит для вызова кода Python из произвольных потоков C. Вместо этого используйте PyGILState API.
Изменено в версии 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:Значение что
Значение 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
, когда функция языка Си вызвала исключение.
-
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 для каждого потока обеспечивает удобное и потокобезопасное место для его хранения. Функция profile вызывается для всех отслеживаемых событий, кромеPyTrace_LINE
PyTrace_OPCODE
иPyTrace_EXCEPTION
.Вызывающий должен удерживать клавишу GIL.
-
void
PyEval_SetTrace
(Py_tracefunc func, PyObject *obj)¶ Установите функцию трассировки на func. Это аналогично
PyEval_SetProfile()
, за исключением того, что функция трассировки получает события, связанные с номерами строк и событиями, относящимися к каждому операционному коду, но не получает никаких событий, связанных с вызовом объектов функций языка Си. Любая функция трассировки, зарегистрированная с помощью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
). API уровня CPython C аналогичны тем, которые предлагаются pthreads и Windows: использование ключа потока и функций для привязки значения void* к потоку.
GIL не нужно удерживать при вызове этих функций; они обеспечивают собственную блокировку.
Обратите внимание, что Python.h
не включает объявление TLS APIs, вам необходимо включить pythread.h
для использования потоково-локального хранения.
Примечание
Ни одна из этих функций API не управляет памятью от имени значений void*. Вы должны выделять и удалять их самостоятельно. Если значения void* окажутся PyObject*, эти функции также не будут выполнять операции refcount для них.
API Thread Specific Storage (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
()¶ - Part of the Stable ABI since version 3.7.
Возвращает значение, которое находится в том же состоянии, что и значение, инициализированное с помощью
Py_tss_NEEDS_INIT
, илиNULL
в случае сбоя динамического распределения.
-
void
PyThread_tss_free
(Py_tss_t *key)¶ - Part of the Stable ABI since version 3.7.
Освободить заданную key, выделенную
PyThread_tss_alloc()
, после первого вызоваPyThread_tss_delete()
, чтобы убедиться, что все связанные локали потоков были освобождены. Это не работает, если аргумент key равен NULL.Примечание
Освобожденный ключ становится висячим указателем. Вы должны сбросить ключ на NULL.
Методы¶
Параметр key этих функций не должен быть NULL
. Более того, поведение PyThread_tss_set()
и PyThread_tss_get()
неопределено, если данная Py_tss_t
не была инициализирована PyThread_tss_create()
.
-
int
PyThread_tss_is_created
(Py_tss_t *key)¶ - Part of the Stable ABI since version 3.7.
Возвращает ненулевое значение, если данный
Py_tss_t
был инициализированPyThread_tss_create()
.
-
int
PyThread_tss_create
(Py_tss_t *key)¶ - Part of the Stable ABI since version 3.7.
Возвращает нулевое значение при успешной инициализации ключа TSS. Поведение не определено, если значение, на которое указывает аргумент key, не инициализировано
Py_tss_NEEDS_INIT
. Эта функция может быть вызвана несколько раз для одного и того же ключа – вызов ее для уже инициализированного ключа является безотказным и немедленно возвращает успех.
-
void
PyThread_tss_delete
(Py_tss_t *key)¶ - Part of the Stable ABI since version 3.7.
Уничтожить ключ TSS, чтобы забыть значения, связанные с ключом, во всех потоках и изменить состояние инициализации ключа на uninitialized. Уничтоженный ключ может быть инициализирован снова с помощью
PyThread_tss_create()
. Эта функция может быть вызвана несколько раз для одного и того же ключа - вызов ее для уже уничтоженного ключа не имеет смысла.
-
int
PyThread_tss_set
(Py_tss_t *key, void *value)¶ - Part of the Stable ABI since version 3.7.
Возвращает нулевое значение, указывающее на успешное связывание значения void* с ключом TSS в текущем потоке. Каждый поток имеет отдельное отображение ключа на значение void*.
-
void *
PyThread_tss_get
(Py_tss_t *key)¶ - Part of the Stable ABI since version 3.7.
Возвращает значение void*, связанное с ключом TSS в текущем потоке. Возвращается
NULL
, если с ключом в текущем потоке не связано ни одно значение.
API Thread Local Storage (TLS)¶
Не рекомендуется, начиная с версии 3.7: Этот API заменен на Thread Specific Storage (TSS) API.
Примечание
Эта версия API не поддерживает платформы, на которых родной ключ TLS определен таким образом, что его нельзя безопасно привести к int
. На таких платформах PyThread_create_key()
будет немедленно возвращаться со статусом отказа, а все остальные функции TLS на таких платформах не работают.
Из-за проблемы совместимости, отмеченной выше, эта версия API не должна использоваться в новом коде.
-
int
PyThread_create_key
()¶ - Part of the Stable ABI.
-
void
PyThread_delete_key
(int key)¶ - Part of the Stable ABI.
-
int
PyThread_set_key_value
(int key, void *value)¶ - Part of the Stable ABI.
-
void *
PyThread_get_key_value
(int key)¶ - Part of the Stable ABI.
-
void
PyThread_delete_key_value
(int key)¶ - Part of the Stable ABI.
-
void
PyThread_ReInitTLS
()¶ - Part of the Stable ABI.