Инициализация, финализация и потоки¶
См. также Инициализацию конфигурации Python.
Перед инициализацией Python¶
В приложении, встраивающем Python, функцию Py_Initialize()
необходимо вызвать перед
использованием любых других функций API Python/C; за исключением нескольких
функций и глобальных переменных конфигурации.
Перед инициализацией Python можно безопасно вызвать следующие функции:
- Функции конфигурирования:
- Информационные функции:
- Утилиты:
- Распределители памяти:
Примечание
Следующие функции не следует вызывать перед
Py_Initialize()
: Py_EncodeLocale()
, Py_GetPath()
,
Py_GetPrefix()
, Py_GetExecPrefix()
,
Py_GetProgramFullPath()
, Py_GetPythonHome()
,
Py_GetProgramName()
и PyEval_InitThreads()
.
Переменные глобальной конфигурации¶
Python содержит переменные для глобальной конфигурации для управления различными функциями и опциями. По умолчанию это флаги, управляемые параметрами командной строки.
Когда флаг устанавливается опцией, значение флага - это количество раз, когда
была установлена эта опция. Например, -b
устанавливает Py_BytesWarningFlag
в 1, и
-bb
устанавливает Py_BytesWarningFlag
в 2.
-
int
Py_BytesWarningFlag
¶ При сравнении
bytes
илиbytearray
сstr
илиbytes
сint
выдается предупреждение. Выдать ошибку, если она больше или равна2
.Задается опцией
-b
.
-
int
Py_DebugFlag
¶ Включить выходные данные отладки парсера (только для специалистов, в зависимости от параметров компиляции).
Задается параметром
-d
и переменной средыPYTHONDEBUG
.
-
int
Py_DontWriteBytecodeFlag
¶ Если установлено ненулевое значение, Python не будет пытаться записать
.pyc
файлы при импорте исходных модулей.Задается параметром
-B
и переменной средыPYTHONDONTWRITEBYTECODE
.
-
int
Py_FrozenFlag
¶ Подавление сообщений об ошибках при вычислении пути поиска модуля в
Py_GetPath()
.Закрытый флаг, использоваться программами
_freeze_importlib
иfrozenmain
.
-
int
Py_HashRandomizationFlag
¶ Значение
1
, если для переменной средыPYTHONHASHSEED
задано непустая строка.Если флаг не равен нулю, прочитать переменную среды
PYTHONHASHSEED
, чтобы инициализировать секретное хэш-начальное число.
-
int
Py_IgnoreEnvironmentFlag
¶ Игнорировать все переменные среды
PYTHON*
, например,PYTHONPATH
иPYTHONHOME
, которые могут быть заданы.
-
int
Py_InspectFlag
¶ Когда сценарий передается в качестве первого аргумента или использоваться параметр
-c
, после выполнения сценария или команды, даже еслиsys.stdin
не представляется терминалом, следует перейти в интерактивный режим.Задается параметром
-i
и переменной средыPYTHONINSPECT
.
-
int
Py_IsolatedFlag
¶ Запуск Python в изолированном режиме. В изолированном режиме
sys.path
не содержит ни каталога сценария, ни каталога пакетов сайта пользователя.Задается опцией
-I
.Добавлено в версии 3.4.
-
int
Py_LegacyWindowsFSEncodingFlag
¶ Если флаг не равен нулю, используется
mbcs
кодировка вместо UTF-8 кодировка для кодировка файловой системы.Значение
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
()¶ Инициализируйте Python интерпретатор. В Python внедрения приложения это должно быть вызвано перед использованием любых других функций API Python/C; несколько исключений см. в Перед инициализацией Python.
При этом инициализируется таблица загруженных модулей (
sys.modules
) и создаются основные модулиbuiltins
,__main__
иsys
. Онаы также инициализирует путь поиска модуля (sys.path
). Она не устанавливаетsys.argv
; использовать для этогоPySys_SetArgvEx()
. Она no-op при повторном вызове (без первого вызоваPy_FinalizeEx()
). Нет возвращаемого значения; это неустранимая ошибка в случае сбоя инициализации.Примечание
В Windows изменяется режим консоли с
O_TEXT
наO_BINARY
, что также повлияет не-Python использование консоли с помощью среды выполнения C.
-
void
Py_InitializeEx
(int initsigs)¶ Функция работает как
Py_Initialize()
, если initsigs1
. Если initsigs0
, он пропускает журналирование инициализации сигнала обработчика, что может оказаться полезным при встраивании 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 интерпретатора. Она no-op при повторном вызове (без повторного вызоваPy_Initialize()
). Обычно возвращает значение0
. Если во время завершения (очистка буферизованных данных) возникли ошибки, возвращается-1
.Функция предусмотрена по ряду причин. Приложение встраивания может перезапустить Python без необходимости перезапуска самого приложения. Приложению, загрузившему Python интерпретатор из динамически загружаемой библиотеки (или DLL), может потребоваться освободить все аллоцированную память путем Python перед выгрузкой DLL. Во время поиска утечек памяти в приложении разработчику может потребоваться освободить всю аллоцированную память Python перед выходом из приложения.
Ошибки и предостережения: уничтожение модулей и объектов в модулях производится в случайном порядке; это может привести к отказу деструкторов (
__del__()
методы), когда они зависят от других объектов (даже функций) или модулей. Динамически загружаемые модули расширения, загруженные Python, не выгружаются. Небольшие объемы памяти, аллоцированные Python интерпретатором, не могут быть освобождены (если вы обнаружите утечку, пожалуйста, сообщите об этом). Память, связанная в циклических ссылках между объектами, не освобождается. Часть памяти, аллоцированная модулями расширения, не может быть освобождена. Некоторые расширения могут работать неправильно, если их процедура инициализации вызывается несколько раз; это может произойти, если приложение вызываетPy_Initialize()
иPy_FinalizeEx()
несколько раз.Raises an auditing event
cpython._PySys_ClearAuditHooks
with no arguments.Добавлено в версии 3.6.
-
void
Py_Finalize
()¶ Обратно совместимая версия
Py_FinalizeEx()
, которая игнорирует возвращаемое значение.
Параметры для всего процесса¶
-
int
Py_SetStandardStreamEncoding
(const char *encoding, const char *errors)¶ Функция должна вызываться перед
Py_Initialize()
, если она вообще вызывается. Она определяет, какую кодировку и обработку ошибок использовать со стандартным вводом-выводом, с теми же значениями, что и вstr.encode()
.Он переопределяет
PYTHONIOENCODING
значения и позволяет встраивать код для управления кодировкой ввода-вывода, когда переменная среды не работает.encoding и/или errors могут быть
NULL
для использованияPYTHONIOENCODING
и/или значения по умолчанию (в зависимости от других настроек).Обратите внимание, что
sys.stderr
всегда использует обработчик ошибки «замены обратного слеша», независимо от этой (или любой другой) настройки.Если вызывается
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
()¶ Возвращает prefix для установленных файлов, не зависящих от платформы. Это происходит через ряд сложных правил из имени программы, заданного с помощью
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-префикс будет'/usr/local'
. Возвращенная строка указывает в статическое хранилище; вызывающий не должен изменять свое значение. Это соответствует переменной exec_prefix вMakefile
верхнего уровня и аргументу--exec-prefix
скрипта configure во время сборки. Этот значение доступено для Python код какsys.exec_prefix
. Это полезно только в Unix.Фон: префикс exec отличается от префикса, когда зависящие от платформы файлы (например, исполняемые файлы и общие библиотеки) устанавливаются в другом дереве каталогов. При обычной установке зависящие от платформы файлы могут быть установлены в поддереве
/usr/local/plat
, в то время как независимые от платформы могут быть установлены в/usr/local
.Вообще говоря, платформа - это сочетание аппаратных и программных семейств, например, машины Sparc под управлением операционной системы Solaris 2.x считаются одной и той же платформой, но машины Intel под управлением Solaris 2.x - другой платформой, а машины Intel под управлением Linux - еще одной платформой. Различные основные версии одной и той же операционной системы, как правило, также образуют различные платформы. Не-Unix операционные системы - это другая история; стратегии установки в этих системах настолько различны, что префикс и exec-префикс не имеют смысла и устанавливаются в пустую строку. Обратить внимание, что собранные файлы Python байткода - независимая платформа (но весьма зависимый от версии Python, которой они были собраны!).
Системные администраторы будут знать, как настроить mount или automount программы для совместного использования
/usr/local
между платформами, при этом/usr/local/plat
каждой платформе должна быть отдельная файловая система.
-
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 версия; первые три символа - основная и вспомогательная версии, разделенные точкой. Возвращенная строка указывает на статическое хранилище; вызывающий не должен изменять свои значения. Это значение доступено для 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)¶ Задать каталог «home» по умолчанию, т.е. расположение стандартных библиотек Python. См.
PYTHONHOME
, чтобы узнать значение строкового аргумента.Аргумент должен указывать на символьную строку с нулевым окончанием в статическом хранилище, содержимое которого не будет изменяться в течение времени выполнения программы. Никакой код в Python интерпретаторе не изменят содержимое этого хранилища.
Используйте
Py_DecodeLocale()
для декодирования байтовой строки полученной изwchar_*
строки.
-
w_char*
Py_GetPythonHome
()¶ Возвращает значение по умолчанию «home», то есть значение, установленное предыдущим вызовом
Py_SetPythonHome()
, или значение переменной средыPYTHONHOME
, если она установлена.
Состояние потока и блокировка глобального интерпретатора¶
Python интерпретатор не полностью потокобезопасной. Для поддержки многопоточных программ Python существует глобальная блокировка, называемая глобальная блокировка интерпретатора или GIL, которая должна удерживаться текущим потоком, прежде чем он сможет безопасно получать доступ к Python объектам. Без блокировки даже самые простые операции могут вызвать проблемы в многопоточной программе: например, когда два потока одновременно увеличивают количество ссылок одного и того же объекта, количество ссылок может в конечном итоге увеличиваться только один раз вместо двух.
Поэтому существует правило, что только поток, получивший GIL, может
работать с Python объектами или вызывать функции API Python/C. Для
имитации параллелизма выполнения интерпретатор регулярно пытается переключиться
потоки (см. sys.setswitchinterval()
). Блокировка также снимается вокруг потенциально
блокирующих I/O операций, таких как чтение или запись файла, так что
другие 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);
Вот то, как эти функции работают: глобальная блокировка интерпретатора используется, чтобы защитить указатель на состояние текущего потока. Отпуская блокировку и экономя состояние потока, текущий указатель состояния потока должен быть восстановлен, прежде чем освободится блокировка (так как другой поток мог немедленно установить блокировку и сохранить его в собственном потоке состояния в глобальной переменной). И наоборот, при захвате блокировки и восстановлении состояния потока блокировка должна быть получена перед сохранением указателя состояния потока.
Примечание
Вызов функций I/O системы является наиболее распространенным вариантом
использования для освобождения GIL, но он также может быть полезен перед вызовом
длительных вычислений, которые не нуждаются в доступе к Python объектам,
таким как сжатие или криптографические функции, работающие с буферами памяти.
Например, стандартные модули zlib
и hashlib
освобождают GIL при сжатии
или хэшировании данных.
Не-Python созданные потоки¶
Когда потоки создаются с использованием специального 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()
), но смешивание нескольких интерпретаторов и
PyGILState_*()
API не поддерживается.
Предостережение от fork()¶
Еще одна важная вещь, которую нужно отметить о потоках - это их поведение
перед вызовом C fork()
. В большинстве систем с fork()
после
процесса будет существовать только поток, выдавший fork. Это оказывает
конкретное влияние как на обработку блокировки, так и на все хранимые
состояния во время выполнения CPython.
Тот факт, что остается только «текущий» поток, означает, что любые
блокировки, удерживаемые другими потоками, никогда не будут освобождены.
Python решает это для os.fork()
, устанавливая блокировки, которые он использует
внутри перед fork, и освобождая их после этого. Кроме того, он сбрасывает
любые Объекты Lock в дочернем. При расширении или встраивании Python нет
возможности информировать Python о дополнительных (не-Python) блокировках,
которые необходимо получить до или сбросить после fork. Для выполнения той же
задачи необходимо pthread_atfork()
такие объекты ОС, как использоваться. Кроме того, при
расширении или встраивании Python вызов fork()
непосредственно, а не
через os.fork()
(и возврат в или вызов в Python) может привести к
взаимоблокировке одной из Python внутренних блокировок, удерживаемых
потоком, которая не существует после fork. PyOS_AfterFork_Child()
пытается сбросить
необходимые блокировки, но не всегда это у него получается.
Тот факт, что все остальные потоки исчезают, также означает, что
состояние выполнения CPython должны быть правильно очищены, что и делает
os.fork()
. Это означает завершение всех других объектов PyThreadState
,
принадлежащих текущему интерпретатору, и всех других объектов PyInterpreterState
. Из-за
этого и особого характера «main» interpreter fork()
следует вызывать только в том
«главном» потоке интерпретатора, где изначально была инициализирована
CPython глобальная среда выполнения. Единственное исключение - если
exec()
будет вызван сразу после.
Высокоуровневый API¶
Это наиболее часто используемые типы и функции при написании расширения C кода, или при встраивании интерпретатора Python:
-
PyInterpreterState
¶ Структура данных представляет состояние, совместно используемую рядом взаимодействующих потоков. Потоки, принадлежащие тому же интерпретатору, совместно используют администрирование модулей и несколько других внутренних элементов. В этой структуре нет публичных членов.
Потоки, принадлежащие различным интерпретаторам, изначально не имеют общего доступа, кроме состояние процессов, таких как доступная память, открытые файловые дескрипторы и т.п. Глобальная блокировка интерпретатора также используется всеми потоками независимо от того, к какому интерпретатору они принадлежат.
-
PyThreadState
¶ Структура данных представляет состояние отдельного потока. Единственным открытым элементом данных является
interp
(PyInterpreterState *
), который указывает на состояние интерпретатора этого потока.
-
void
PyEval_InitThreads
()¶ Инициализация и получение глобальной блокировки интерпретатора. Он должен вызываться в основном потоке перед созданием второго потока или участием в любых других потоковых операциях, таких как
PyEval_ReleaseThread(tstate)
. Он не нужен перед вызовомPyEval_SaveThread()
илиPyEval_RestoreThread()
.Это «no-op» при повторном вызове.
Изменено в версии 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
()¶ Убедиться, что текущий поток готов к вызову API Python C независимо от текущего состояния Python или глобальной блокировки интерпретатора. Это может вызываться потоком столько раз, сколько требуется, пока каждый вызов сопоставляется с вызовом
PyGILState_Release()
. Как правило, другие API поток-зависимые могут использоваться между вызовамиPyGILState_Ensure()
иPyGILState_Release()
, пока состояние потока восстанавливается до предыдущего состояния перед Release(). Например, допустимо нормальное использование макросовPy_BEGIN_ALLOW_THREADS
иPy_END_ALLOW_THREADS
.Возвращает значение - непрозрачный «обработчик» к состоянию потока, когда
PyGILState_Ensure()
вызывается и нужно передать кPyGILState_Release()
, чтобы гарантировать, что Python останется в том же состоянии. Несмотря на то, что рекурсивные вызовы разрешены, эти дескрипторы не могут быть общими - каждый уникальный вызовPyGILState_Ensure()
должен сохранять дескриптор для вызоваPyGILState_Release()
.Когда функция возвращает, текущий поток удерживает GIL и может вызывать произвольные Python код. Сбой является неустранимой ошибкой.
Примечание
Вызов этой функции из потока при завершении выполнения приведет к прекращению потока, даже если поток не был создан Python. Можно использовать
_Py_IsFinalizing()
илиsys.is_finalizing()
, чтобы проверить, находится ли интерпретатор в процессе завершения перед вызовом этой функции, чтобы избежать нежелательного прерывания.
-
void
PyGILState_Release
(PyGILState_STATE)¶ Освободить все ранее занятые ресурсы. После этого вызова состояние Python совпадет с ним, которое было до соответствующего вызова
PyGILState_Ensure()
(но обычно этот состояние будет неизвестен вызывающему, следовательно использование API GILState).Каждому вызову
PyGILState_Ensure()
должен соответствовать вызовPyGILState_Release()
на одном и том же поток.
-
PyThreadState*
PyGILState_GetThisThreadState
()¶ Получить текущий состояние потока для данного потока. Может возвращать
NULL
, если на текущем потоке не было использовано API GLIEState. Обратите внимание, что главный поток всегда содержит состояние потока, даже если на главном потоке не было сделано вызова авто-поток-состояни. В основном это функция помощника/диагностики.
-
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¶
Все следующие функции должны вызываться после Py_Initialize()
.
Изменено в версии 3.7: Py_Initialize()
теперь инициализирует GIL.
-
PyInterpreterState*
PyInterpreterState_New
()¶ Создать новый объект состояния интерпретатора. Глобальная блокировка интерпретатора не должна удерживаться, но может удерживаться, если необходимо сериализовать вызовы этой функции.
Raises an auditing event
cpython.PyInterpreterState_New
with no arguments.
-
void
PyInterpreterState_Clear
(PyInterpreterState *interp)¶ Сброс всей информации в объекте состояния интерпретатора. Глобальная блокировка интерпретатора должна быть сохранена.
Raises an auditing event
cpython.PyInterpreterState_Clear
with no arguments.
-
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
()¶ - Return value: Borrowed reference.
Возвращает словарь, в котором расширения могут хранить поток-специфичные информацию состояния. Каждое расширение должно использовать уникальный ключ для хранения состояние в словаре. Эту функцию можно вызвать, если текущее состояние потока недоступно. Если эта функция возвращает
NULL
, исключение не возникает, и вызывающий должен предположить, что текущее состояние потока недоступно.
-
int
PyThreadState_SetAsyncExc
(unsigned long id, PyObject *exc)¶ Асинхронное создание исключения в потоке. Аргумент id - id потока целевого потока; exc является объектом исключения, который необходимо создать. Функция не крадет никаких ссылок на exc. Чтобы предотвратить наивное неправильное использование, необходимо написать собственное расширение 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_SaveThread()
является функцией более высокого уровня, которая всегда доступна (даже если потоки не были инициализированы).
-
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()
.
Поддержка подинтерпретатора¶
Хотя в большинстве случаев используется только один Python интерпретатор, существуют случаи, когда необходимо создать несколько независимых интерпретаторов в одном и том же процессе и, возможно, даже в одном и том же потоке. Подинтерпретаторы позволяют вам это делать.
«Основной» интерпретатор - первый, созданный при инициализации среды выполнения.
Обычно это единственный Python интерпретатор в процессе. В отличие от
субинтерпертеров, основной интерпретатор имеет уникальные глобальные функции
обработки сигналов. Он также отвечает за выполнение во время инициализации среды
выполнения и обычно является активным интерпретатором во время завершения среды
выполнения. Функция PyInterpreterState_Main()
возвращает указатель на ее состояние.
С помощью функции PyThreadState_Swap()
можно переключаться между подчиненными
интерпретаторами. Их можно создавать и уничтожать с помощью следующих функций:
-
PyThreadState*
Py_NewInterpreter
()¶ Создание нового подинтерпретатора. Это (почти) полностью отдельная среда для выполнения Python кода. В частности, новый интерпретатор имеет отдельные независимые версии всех импортированных модулей, включая фундаментальные модули
builtins
,__main__
иsys
. Таблица загруженных модулей (sys.modules
) и путь поиска модулей (sys.path
) также являются отдельными. Новая среда не имеетsys.argv
переменной. Он имеет новые стандартные объекты I/O потокового файлаsys.stdin
,sys.stdout
иsys.stderr
(однако они относятся к одному и тому же базовому файловому дескриптору).Возвращаемое значение указывает на первое состояние потока, созданный в новом подинтерпретаторе. Это состояние потока выполняется в текущем состоянии потока. Следует отметить, что фактические поток не создаются; см. обсуждение состояния потока ниже. При неудачном создании нового интерпретатора возвращается
NULL
; исключение не установлено, так как состояние исключения хранится в текущем состоянии потока и не может быть состояния текущего потока. (Как и все другие функции API Python/C, глобальная блокировка интерпретатора должна удерживаться перед вызовом этой функции и сохраняется при ее возвращении; однако, в отличие от большинства других функций API Python/C, нет необходимости в текущем состоянии потока при вводе.)Модули расширения совместно используются (суб-) интерпретаторами следующим образом
Для модулей, использующих многофазную инициализацию, например
PyModule_FromDefAndSpec()
, для каждого интерпретатора создается и инициализируется отдельный объект модуля. Эти объекты модуля совместно используют только статические и глобальные переменные уровня C.Для модулей, использующих однофазную инициализацию, например,
PyModule_Create()
, при первом импорте конкретного расширения он инициализируется нормально, и (неглубокая) копия словаря его модуля удаляется. Когда это расширение импортируется другим (суб-) интерпретатором, новый модуль инициализируется и заполняется содержимым этой копии; функцияinit
внутреннего абонента не вызывается. Таким образом, объекты в словаре модуля совместно используются (суб-) интерпретаторами, что может вызвать нежелательное поведение (см. Ошибки и предостережения ниже).Следует отметить, что это отличается от того, что происходит при импорте внутренней линии после полной повторной инициализации интерпретатора путем вызова
Py_FinalizeEx()
иPy_Initialize()
; в этом случае функцияinitmodule
будет вызвана повторно. Как и в случае многофазной инициализации, это означает, что только статические и глобальные переменные уровня C совместно используются этими модулями.
-
void
Py_EndInterpreter
(PyThreadState *tstate)¶ Уничтожить (суб-) интерпретатор, представленный данным состоянием потока. Данное состояние потока должно быть текущим состоянием потока. См. обсуждение состояния потока ниже. Когда вызов возвращает, текущий поток состояния
NULL
. Все потоки состояния, связанные с этим интерпретатором, уничтожаются. (Глобальная блокировка интерпретатора должна быть удержана перед вызовом этой функции и по-прежнему удерживается при ее возвращении.)Py_FinalizeEx()
уничтожит всех субинтерпретаторов, которые не были явно уничтожены на этот момент.
Ошибки и предостережения¶
Поскольку субинтерпресеры (и основные интерпретатор) являются частью одного и того
же процесса, изоляция между ними не идеальна — например, используя
низкоуровневое файловые операции, как os.close()
они могут (случайно или
злонамеренно) влиять на открытые файлы друг друга. Из-за способа совместного
использования расширений (суб-)интерпретаторами некоторые расширения могут
работать неправильно; это особенно вероятно при использовании однофазной
инициализации или (статических) глобальных переменных. Можно вставить объекты,
созданные в одном подинтерпретаторе, в пространство имен другого (суб-)
интерпретатора; по возможности этого следует избегать.
Следует проявлять особую осторожность, чтобы избежать совместного использования пользовательских функций, методов, сущностей или классов субинтерпертерами, поскольку операции импорта, выполняемые такими объектами, могут повлиять на неправильный (суб-)интерпретатор словарь загруженных модулей. Не менее важно избегать совместного использования объектов, из которых можно получить доступ к вышеуказанным объектам.
Также обратить внимание, что объединение этой функциональности с API PyGILState_*()
тонкое, потому что эти API принимают взаимно однозначное соответствие между
состояниями Python потока и уровнем потоков ОС, предположение,
сломанное присутствием подинтерпретаторов. Настоятельно рекомендуется не
переключать вспомогательные интерпретаторы между парой соответствующих
PyGILState_Ensure()
и PyGILState_Release()
вызовов. Кроме того,
расширения (такие как ctypes
)
использующий эти API, чтобы позволить вызвать Python код из
созданных не-Python потоков будут, вероятно, сломаны, используя
подинтерпретаторы.
Асинхронные уведомления¶
Предусмотрен механизм асинхронного уведомления основного потока интерпретатора. Эти уведомления принимают форму указателя функции и аргумента 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.
Профилирование и трассировка¶
В 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.
Расширенная поддержка отладчика¶
Функции предназначены только для использоваться усовершенствованными средствами отладки.
-
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 аналогичны API, предлагаемым pthreads и
Windows: используется ключ потока и функции, чтобы связать void*
значение для потока.
GIL не нужно удерживать при вызове этих функций; они устанавливают свою собственную блокировку.
Обратите внимание, что Python.h
не включает объявление TLS API, необходимо
подключить pythread.h
для использования поток-локального хранилища.
Примечание
Ни одна из этих функций API не обрабатывает управление памятью от имени значений
void*
. Вам нужно выделить и освободить их самостоятельно. Если
значения void*
совпадают с PyObject*
, эти функции также не
выполняют с ними операций refcount.
API хранилища для конкретных потоков (TSS)¶
Интерфейс TSS API заменяет собой существующий интерфейс 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.
Динамическое распределение¶
Динамическое выделение 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)¶ Освободить данный key, аллоцированный
PyThread_tss_alloc()
, после первого вызоваPyThread_tss_delete()
чтобы убедиться, что все связанные с потоком локальные не назначены. Это операция no-op, если аргумент 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)¶ Возвращает ненулевое значение, если данный
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()
. Функция может быть вызвана повторно на одном ключе - вызов ее на уже уничтоженном ключе является no-op.
API локального хранилища потоков (TLS)¶
Не рекомендуется, начиная с версии 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
()¶