Содержание страницы
Состояния потоков и глобальная блокировка интерпретатора¶Thread states and the global interpreter lock
За исключением сборки со свободной многопоточностью CPython, интерпретатор Python в целом не является потокобезопасным. Для поддержки многопоточных программ на Python существует глобальная блокировка, называемая глобальной блокировкой интерпретатора, или GIL, которую поток должен захватить перед доступом к объектам Python. Без этой блокировки даже простейшие операции могут вызвать проблемы в многопоточной программе: например, если два потока одновременно увеличивают счётчик ссылок одного и того же объекта, счётчик может увеличиться только один раз вместо двух.
Таким образом, только поток, удерживающий GIL, может работать с объектами Python или вызывать C API Python.
Для эмуляции параллелизма интерпретатор регулярно пытается переключать потоки между инструкциями байт-кода (см. sys.setswitchinterval()). Поэтому блокировки также необходимы для потокобезопасности в коде на чистом Python.
Кроме того, глобальная блокировка интерпретатора освобождается вокруг блокирующих операций ввода-вывода, таких как чтение или запись в файл. В C API это делается с помощью отсоединения состояния потока.
Интерпретатор Python хранит некоторую локальную для потока информацию внутри структуры данных, называемой PyThreadState, известной как состояние потока. Каждый поток имеет указатель, локальный для потока, на PyThreadState; состояние потока, на которое ссылается этот указатель, считается присоединённым.
Поток может иметь только одно присоединённое состояние потока в каждый момент времени. Присоединённое состояние потока обычно аналогично удержанию GIL, за исключением сборок со свободной многопоточностью. В сборках с включённым GIL присоединение состояния потока будет блокироваться до тех пор, пока не будет получен GIL. Однако даже в сборках с отключённым GIL всё равно требуется иметь присоединённое состояние потока, поскольку интерпретатору необходимо отслеживать, какие потоки могут обращаться к объектам Python.
Примечание
Даже в сборке со свободной многопоточностью присоединение состояния потока может блокироваться, так как GIL может быть повторно включён, или потоки могут быть временно приостановлены (например, во время сборки мусора).
Обычно при использовании C API Python всегда есть присоединённое состояние потока, в том числе при встраивании и реализации методов, так что необходимость самостоятельно настраивать состояние потока возникает редко. Только в некоторых особых случаях, например в блоке Py_BEGIN_ALLOW_THREADS или в новом потоке, поток не будет иметь присоединённого состояния потока. Если есть сомнения, проверьте, возвращает ли PyThreadState_GetUnchecked() NULL.
Если всё же потребуется создать состояние потока, вызовите PyThreadState_New(),
затем PyThreadState_Swap(), или воспользуйтесь опасной
функцией PyGILState_Ensure().
Отсоединение состояния потока из кода расширения¶Detaching the thread state from extension code
Большая часть кода расширения, работающего с состоянием потока, имеет следующую простую структуру:
Save the thread state in a local variable.
... Do some blocking I/O operation ...
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 удерживается для интерпретатора. Чтобы отсоединить его, вызывается PyEval_SaveThread(), и результат сохраняется в локальной переменной.
Отсоединяя состояние потока, GIL освобождается, что позволяет другим потокам присоединиться к интерпретатору и выполняться, пока текущий поток выполняет блокирующий ввод-вывод. Когда операция ввода-вывода завершается, старое состояние потока повторно присоединяется вызовом PyEval_RestoreThread(), который будет ожидать, пока не удастся захватить GIL.
Примечание
Выполнение блокирующего ввода-вывода – самый распространённый случай применения отсоединения состояния потока, но его также полезно вызывать в длительном нативном коде, которому не нужен доступ к объектам Python или C API Python. Например, стандартные модули zlib и hashlib отсоединяют состояние потока при сжатии или хешировании данных.
В сборке со свободной многопоточностью GIL обычно не рассматривается, но отсоединение состояния потока всё равно требуется, потому что интерпретатору периодически нужно блокировать все потоки для получения согласованного представления объектов Python без риска состояний гонки. Например, CPython в настоящее время приостанавливает все потоки на короткое время во время работы сборщика мусора.
Предупреждение
Отсоединение состояния потока может привести к непредсказуемому поведению при завершении работы интерпретатора. Подробнее см. Предостережения по поводу завершения выполнения.
API¶APIs
Следующие макросы обычно используются без точки с запятой в конце; примеры использования можно найти в дистрибутиве исходного кода Python.
Примечание
Эти макросы всё ещё необходимы в сборке со свободной многопоточностью для предотвращения взаимоблокировок.
-
Py_BEGIN_ALLOW_THREADS¶
- Часть Stable ABI.
Этот макрос раскрывается в
{ PyThreadState *_save; _save = PyEval_SaveThread();. Обратите внимание, что он содержит открывающую фигурную скобку; она должна быть сопоставлена с последующим макросомPy_END_ALLOW_THREADS. См. выше дополнительное обсуждение этого макроса.
-
Py_END_ALLOW_THREADS¶
- Часть Stable ABI.
Этот макрос раскрывается в
PyEval_RestoreThread(_save); }. Обратите внимание, что он содержит закрывающую фигурную скобку; она должна быть сопоставлена с предыдущим макросомPy_BEGIN_ALLOW_THREADS. См. выше дополнительное обсуждение этого макроса.
-
Py_BLOCK_THREADS¶
- Часть Stable ABI.
Этот макрос разворачивается в
PyEval_RestoreThread(_save);: он эквивалентенPy_END_ALLOW_THREADSбез закрывающей фигурной скобки.
-
Py_UNBLOCK_THREADS¶
- Часть Stable ABI.
Этот макрос разворачивается в
_save = PyEval_SaveThread();: он эквивалентенPy_BEGIN_ALLOW_THREADSбез открывающей фигурной скобки и объявления переменной.
Потоки, созданные не из Python¶Non-Python created threads
Когда потоки создаются с помощью специальных Python API (таких как модуль threading), состояние потока автоматически связывается с ними.
Однако, когда поток создается из нативного кода (например, сторонней библиотекой с собственным управлением потоками), он не имеет прикрепленного состояния потока.
Если нужно вызвать код Python из этих потоков (часто это будет частью колбэк-API, предоставляемого вышеупомянутой сторонней библиотекой), необходимо сначала зарегистрировать эти потоки в интерпретаторе, создав новое состояние потока и прикрепив его.
Самый надёжный способ – использовать PyThreadState_New(), а затем
PyThreadState_Swap().
Примечание
PyThreadState_New требует аргумента, указывающего на нужный
интерпретатор; такой указатель можно получить вызовом
PyInterpreterState_Get() из кода, в котором был создан
поток.
Например:
/* Возвращаемое значение PyInterpreterState_Get() из
функции, создавшей этот поток. */
PyInterpreterState *interp = thread_data->interp;
/* Создаёт новое состояние потока для интерпретатора. Оно не начинается как
присоединённым. */
PyThreadState *tstate = PyThreadState_New(interp);
/* Присоединить состояние потока, что приведёт к захвату GIL. */
PyThreadState_Swap(tstate);
/* Выполнить действия Python здесь. */
result = CallSomeFunction();
/* вычислить результат или обработать исключение */
/* Уничтожить состояние потока. После этой точки API Python не допускается. */
PyThreadState_Clear(tstate);
PyThreadState_DeleteCurrent();
Предупреждение
Если интерпретатор завершил работу до вызова PyThreadState_Swap, то
interp окажется висячим указателем!
Устаревший API¶Legacy API
Ещё один распространённый способ вызова кода Python из потока, созданного не в Python, – использовать
PyGILState_Ensure(), а затем вызвать PyGILState_Release().
Эти функции плохо работают, когда в процессе Python существует несколько интерпретаторов.
Если ни один интерпретатор Python ещё не использовался в текущем потоке (что
характерно для потоков, созданных вне Python), PyGILState_Ensure создаст
и присоединит состояние потока для «главного» интерпретатора (первого интерпретатора в
процессе Python).
Кроме того, эти функции имеют проблемы с потоко-безопасностью при
завершении интерпретатора. Использование PyGILState_Ensure во время завершения, скорее всего,
приведёт к аварийному завершению процесса.
Использование этих функций выглядит так:
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
/* Выполнить действия Python здесь. */
result = CallSomeFunction();
/* вычислить результат или обработать исключение */
/* Освободить поток. После этой точки API Python не допускается. */
PyGILState_Release(gstate);
Предостережения относительно fork()¶Cautions about fork()
Ещё одна важная особенность потоков – их поведение при вызове C fork(). На большинстве систем с fork() после
fork процесса остаётся только тот поток, который вызвал fork. Это
оказывает конкретное влияние как на обработку блокировок, так и на всё сохранённое состояние
в среде выполнения CPython.
Тот факт, что остаётся только «текущий» поток, означает, что любые блокировки, удерживаемые другими потоками, никогда не будут освобождены. Python решает эту проблему для os.fork(), захватывая блокировки, которые он использует внутренне, перед fork и освобождая их после. Кроме того, он сбрасывает все
объекты блокировки в дочернем процессе. При расширении или встраивании Python нет способа сообщить Python о дополнительных (не-Python) блокировках, которые необходимо захватить перед fork или сбросить после него. Для достижения того же эффекта потребуется использовать системные механизмы, такие как
pthread_atfork().
Кроме того, при расширении или встраивании Python вызов fork() напрямую, а не через os.fork() (и возврат к вызову Python) может привести к взаимоблокировке из-за того, что одна из внутренних блокировок Python удерживается потоком, который становится недействительным после fork.
PyOS_AfterFork_Child() пытается сбросить необходимые блокировки, но не всегда может это сделать.
Тот факт, что все остальные потоки исчезают, также означает, что состояние среды выполнения CPython должно быть правильно очищено, что и делает os.fork(). Это означает завершение всех остальных объектов PyThreadState, принадлежащих текущему интерпретатору, и всех остальных объектов PyInterpreterState. Из-за этого и особой природы «главного» интерпретатора, fork() следует вызывать только в «главном» потоке этого интерпретатора, где изначально была инициализирована глобальная среда выполнения CPython. Единственное исключение – если exec() будет вызван сразу после.
Высокоуровневые API¶High-level APIs
Это наиболее часто используемые типы и функции при написании многопоточных расширений на C.
-
type PyThreadState¶
- Часть Limited API (как непрозрачная структура).
Эта структура данных представляет состояние одного потока. Единственный открытый элемент данных:
-
PyInterpreterState *interp¶
Состояние интерпретатора этого потока.
-
PyInterpreterState *interp¶
-
void PyEval_InitThreads()¶
- Часть Stable ABI.
Устаревшая функция, которая ничего не делает.
В Python 3.6 и старше эта функция создавала GIL, если его не существовало.
Изменено в версии 3.9: Теперь функция ничего не делает.
Изменено в версии 3.7: Теперь эта функция вызывается
Py_Initialize(), так что вам больше не нужно вызывать её самостоятельно.Изменено в версии 3.2: Эту функцию больше нельзя вызывать до
Py_Initialize().Устарело с версии 3.9.
-
PyThreadState *PyEval_SaveThread()¶
- Часть Stable ABI.
Отсоединить присоединённое состояние потока и вернуть его. После возврата у потока не будет состояния потока.
-
void PyEval_RestoreThread(PyThreadState *tstate)¶
- Часть Stable ABI.
Установить присоединённое состояние потока в tstate. Переданное состояние потока не должно быть присоединённым, иначе произойдёт взаимоблокировка. tstate будет присоединён после возврата.
Примечание
Вызов этой функции из потока во время завершения выполнения приведёт к зависанию потока до выхода из программы, даже если поток не был создан Python. Подробнее см. Предостережения по поводу завершения выполнения.
Изменено в версии 3.14: При вызове во время завершения работы интерпретатора текущий поток зависает, а не завершается.
-
PyThreadState *PyThreadState_Get()¶
- Часть Stable ABI.
Возвращает прикреплённое состояние потока. Если у потока нет прикреплённого состояния потока (например, при нахождении внутри блока
Py_BEGIN_ALLOW_THREADS), то возникает фатальная ошибка (поэтому вызывающему коду не нужно проверятьNULL).См. также
PyThreadState_GetUnchecked().
-
PyThreadState *PyThreadState_GetUnchecked()¶
Аналогично
PyThreadState_Get(), но не завершает процесс фатальной ошибкой, если значение равно NULL. Вызывающий код должен самостоятельно проверить, не является ли результат NULL.Добавлено в версии 3.13: В версиях Python с 3.5 по 3.12 эта функция была приватной и называлась
_PyThreadState_UncheckedGet().
-
PyThreadState *PyThreadState_Swap(PyThreadState *tstate)¶
- Часть Stable ABI.
Устанавливает прикреплённое состояние потока равным tstate и возвращает состояние потока, которое было прикреплено до вызова.
Эту функцию можно безопасно вызывать без прикреплённого состояния потока; она просто вернёт
NULL, указывая, что предыдущего состояния потока не было.См. также
Примечание
Аналогично
PyGILState_Ensure(), эта функция приведёт к зависанию потока, если среда выполнения завершает работу.
API состояния GIL¶GIL-state APIs
Следующие функции используют локальное хранилище потока и несовместимы с подынтерпретаторами:
-
type PyGILState_STATE¶
- Часть Stable ABI.
Тип значения, возвращаемого
PyGILState_Ensure()и передаваемого вPyGILState_Release().-
enumerator PyGILState_LOCKED¶
GIL уже был захвачен, когда была вызвана
PyGILState_Ensure().
-
enumerator PyGILState_UNLOCKED¶
GIL не был захвачен, когда была вызвана
PyGILState_Ensure().
-
enumerator PyGILState_LOCKED¶
-
PyGILState_STATE PyGILState_Ensure()¶
- Часть Stable ABI.
Гарантирует, что текущий поток готов вызывать Python C API независимо от текущего состояния Python или присоединённого состояния потока. Эта функция может вызываться потоком сколько угодно раз, при условии, что каждый вызов сопровождается вызовом
PyGILState_Release(). В целом, другие потоковые API могут использоваться между вызовамиPyGILState_Ensure()иPyGILState_Release(), если состояние потока восстанавливается в предыдущее состояние до вызова Release(). Например, обычное использование макросовPy_BEGIN_ALLOW_THREADSиPy_END_ALLOW_THREADSдопустимо.Возвращаемое значение – это непрозрачный «дескриптор» присоединённого состояния потока на момент вызова
PyGILState_Ensure(), и его необходимо передать вPyGILState_Release(), чтобы гарантировать, что Python останется в том же состоянии. Несмотря на то, что рекурсивные вызовы разрешены, эти дескрипторы нельзя совместно использовать – каждый уникальный вызовPyGILState_Ensure()должен сохранить дескриптор для своего вызоваPyGILState_Release().Когда функция возвращает управление, будет присоединённое состояние потока и поток сможет вызывать произвольный код Python. Сбой является фатальной ошибкой.
Предупреждение
Вызов этой функции во время завершения выполнения небезопасен. Это либо приведёт к зависанию потока до завершения программы, либо, в редких случаях, вызовет полный крах интерпретатора. Подробнее см. Предостережения по поводу завершения выполнения.
Изменено в версии 3.14: При вызове во время завершения работы интерпретатора текущий поток зависает, а не завершается.
-
void PyGILState_Release(PyGILState_STATE)¶
- Часть Stable ABI.
Освобождает любые ресурсы, полученные ранее. После этого вызова состояние Python будет таким же, как до соответствующего вызова
PyGILState_Ensure()(но обычно это состояние неизвестно вызывающему, поэтому используется GILState API).Каждый вызов
PyGILState_Ensure()должен сопровождаться вызовомPyGILState_Release()в том же потоке.
-
PyThreadState *PyGILState_GetThisThreadState()¶
- Часть Stable ABI.
Получает прикреплённое состояние потока для этого потока. Может вернуть
NULL, если на текущем потоке не использовался GILState API. Обратите внимание, что главный поток всегда имеет такое состояние потока, даже если на главном потоке не было вызова auto-thread-state. В основном это вспомогательная/диагностическая функция.Примечание
Эта функция может вернуть не-
NULL, даже если состояние потока отсоединено. Для большинства случаев предпочтительнее использоватьPyThreadState_Get()илиPyThreadState_GetUnchecked().См. также
-
int PyGILState_Check()¶
Возвращает
1, если текущий поток удерживает GIL, и0в противном случае. Эту функцию можно вызывать из любого потока в любое время. Только если её состояние потока было инициализировано черезPyGILState_Ensure(), она вернёт1. В основном это вспомогательная/диагностическая функция. Она может быть полезна, например, в контекстах колбэков или функций выделения памяти, когда знание того, что GIL заблокирован, может позволить вызывающему выполнять чувствительные действия или иначе вести себя по-другому.Примечание
Если текущий процесс Python когда-либо создавал подынтерпретатор, эта функция будет всегда возвращать
1. Для большинства случаев предпочтительнее использоватьPyThreadState_GetUnchecked().Добавлено в версии 3.4.
Низкоуровневые API¶Low-level APIs
-
PyThreadState *PyThreadState_New(PyInterpreterState *interp)¶
- Часть Stable ABI.
Создаёт новый объект состояния потока, принадлежащий указанному объекту интерпретатора. Прикреплённое состояние потока не требуется.
-
void PyThreadState_Clear(PyThreadState *tstate)¶
- Часть Stable ABI.
Сбрасывает всю информацию в объекте состояния потока. tstate должно быть прикреплено.
Изменено в версии 3.9: Теперь эта функция вызывает колбэк
PyThreadState.on_delete. Ранее это происходило вPyThreadState_Delete().Изменено в версии 3.13: Колбэк
PyThreadState.on_deleteудалён.
-
void PyThreadState_Delete(PyThreadState *tstate)¶
- Часть Stable ABI.
Уничтожает объект состояния потока. tstate не должно быть прикреплено ни к какому потоку. tstate должно быть предварительно сброшено вызовом
PyThreadState_Clear().
-
void PyThreadState_DeleteCurrent(void)¶
Открепляет прикреплённое состояние потока (которое должно быть предварительно сброшено вызовом
PyThreadState_Clear()) и затем уничтожает его.После возврата никакое состояние потока не будет прикреплено.
-
PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate)¶
- Часть Stable ABI начиная с версии 3.10.
Возвращает текущий кадр состояния потока Python tstate.
Возвращает сильную ссылку. Возвращает
NULL, если в данный момент кадр не выполняется.См. также
PyEval_GetFrame().tstate не должен быть
NULLи должен быть прикреплён.Добавлено в версии 3.9.
-
uint64_t PyThreadState_GetID(PyThreadState *tstate)¶
- Часть Stable ABI начиная с версии 3.10.
Возвращает уникальный идентификатор состояния потока для состояния потока Python tstate.
tstate не должен быть
NULLи должен быть прикреплён.Добавлено в версии 3.9.
-
PyInterpreterState *PyThreadState_GetInterpreter(PyThreadState *tstate)¶
- Часть Stable ABI начиная с версии 3.10.
Возвращает интерпретатор состояния потока Python tstate.
tstate не должен быть
NULLи должен быть прикреплён.Добавлено в версии 3.9.
-
void PyThreadState_EnterTracing(PyThreadState *tstate)¶
Приостанавливает трассировку и профилирование в состоянии потока Python tstate.
Возобновляет их с помощью функции
PyThreadState_LeaveTracing().Добавлено в версии 3.12.
-
void PyThreadState_LeaveTracing(PyThreadState *tstate)¶
Возобновляет трассировку и профилирование в состоянии потока Python tstate, приостановленные функцией
PyThreadState_EnterTracing().См. также функции
PyEval_SetTrace()иPyEval_SetProfile().Добавлено в версии 3.12.
-
int PyUnstable_ThreadState_SetStackProtection(PyThreadState *tstate, void *stack_start_addr, size_t stack_size)¶
- Это нестабильное API. Оно может меняться без предупреждения в минорных версиях.
Устанавливает начальный адрес защиты стека и размер защиты стека состояния потока Python.
В случае успеха возвращает
0. В случае неудачи устанавливает исключение и возвращает-1.CPython реализует контроль рекурсии для кода на C, вызывая
RecursionError, когда замечает, что стек выполнения машины близок к переполнению. См., например, функциюPy_EnterRecursiveCall(). Для этого ему нужно знать расположение стека текущего потока, которое он обычно получает от операционной системы. При изменении стека, например, с помощью методов переключения контекста, таких какboost::contextбиблиотеки Boost, необходимо вызватьPyUnstable_ThreadState_SetStackProtection(), чтобы сообщить CPython об изменении.Необходимо вызвать
PyUnstable_ThreadState_SetStackProtection()либо до, либо после изменения стека. Не следует вызывать другие функции Python C API между этим вызовом и изменением стека.Для отмены этой операции см.
PyUnstable_ThreadState_ResetStackProtection().Добавлено в версии 3.15.
-
void PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate)¶
- Это нестабильное API. Оно может меняться без предупреждения в минорных версиях.
Сбрасывает начальный адрес защиты стека и размер защиты стека состояния потока Python в значения по умолчанию операционной системы.
Пояснение см. в
PyUnstable_ThreadState_SetStackProtection().Добавлено в версии 3.15.
-
PyObject *PyThreadState_GetDict()¶
- Возвращаемое значение: заимствованная ссылка. Часть Stable ABI.
Возвращает словарь, в котором расширения могут хранить информацию о состоянии, специфичном для потока. Каждое расширение должно использовать уникальный ключ для хранения состояния в словаре. Эту функцию можно вызывать, когда состояние потока не прикреплено. Если эта функция возвращает
NULL, никакое исключение не было возбуждено, и вызывающий должен считать, что состояние потока не прикреплено.
-
void PyEval_AcquireThread(PyThreadState *tstate)¶
- Часть Stable ABI.
Прикрепляет tstate к текущему потоку, который не должен быть
NULLили уже прикреплён.Вызывающий поток не должен уже иметь прикреплённого состояния потока.
Примечание
Вызов этой функции из потока, когда среда выполнения завершается, приведёт к зависанию потока до выхода из программы, даже если поток не был создан Python. Подробнее см. в Предостережения относительно завершения работы среды выполнения.
Изменено в версии 3.8: Функция обновлена для согласованности с
PyEval_RestoreThread(),Py_END_ALLOW_THREADS()иPyGILState_Ensure(), и теперь завершает текущий поток, если вызвана во время завершения работы интерпретатора.Изменено в версии 3.14: При вызове во время завершения работы интерпретатора текущий поток зависает, а не завершается.
PyEval_RestoreThread()– функция более высокого уровня, которая всегда доступна (даже если потоки не были инициализированы).
-
void PyEval_ReleaseThread(PyThreadState *tstate)¶
- Часть Stable ABI.
Открепляет прикреплённое состояние потока. Аргумент tstate, который не должен быть
NULL, используется только для проверки того, что он представляет прикреплённое состояние потока – если это не так, сообщается о фатальной ошибке.PyEval_SaveThread()– функция более высокого уровня, которая всегда доступна (даже если потоки не были инициализированы).
Асинхронные уведомления¶Asynchronous notifications
Предоставляется механизм для асинхронных уведомлений основному потоку интерпретатора. Эти уведомления имеют форму указателя на функцию и аргумента в виде указателя void.
-
int Py_AddPendingCall(int (*func)(void*), void *arg)¶
- Часть Stable ABI.
Планирует вызов функции из основного потока интерпретатора. В случае успеха возвращается
0, и func помещается в очередь для вызова в основном потоке. В случае неудачи возвращается-1без установки какого-либо исключения.При успешной постановке в очередь func будет в конечном итоге вызвана из основного потока интерпретатора с аргументом arg. Она будет вызвана асинхронно по отношению к нормально выполняющемуся коду Python, но при соблюдении обоих этих условий:
на границе байткода;
при удержании основным потоком присоединённого состояния потока (поэтому func может использовать полный C API).
func должна возвращать
0при успехе или-1при неудаче с установленным исключением. func не будет прервана для выполнения другого асинхронного уведомления рекурсивно, но всё же может быть прервана для переключения потоков, если состояние потока отсоединено.Эта функция не требует присоединённого состояния потока. Однако для вызова этой функции в подынтерпретаторе вызывающий должен иметь присоединённое состояние потока. В противном случае функция func может быть запланирована для вызова из неправильного интерпретатора.
Предупреждение
Это низкоуровневая функция, полезная только в особых случаях. Нет гарантии, что func будет вызвана максимально быстро. Если главный поток занят выполнением системного вызова, func не будет вызвана до возврата из системного вызова. Эта функция в целом не подходит для вызова кода Python из произвольных C-потоков. Вместо неё используйте PyGILState API.
Добавлено в версии 3.1.
Изменено в версии 3.9: Если эта функция вызывается в подынтерпретаторе, функция func теперь планируется для вызова из подынтерпретатора, а не из основного интерпретатора. Каждый подынтерпретатор теперь имеет свой собственный список запланированных вызовов.
Изменено в версии 3.12: Эта функция теперь всегда планирует выполнение func в основном интерпретаторе.
-
int Py_MakePendingCalls(void)¶
- Часть Stable ABI.
Выполняет все отложенные вызовы. Обычно это выполняется автоматически интерпретатором.
Эта функция возвращает
0при успехе и-1с установленным исключением при ошибке.Если эта функция вызывается не в основном потоке главного интерпретатора, она ничего не делает и возвращает
0. Вызывающий должен удерживать присоединённое состояние потока.Добавлено в версии 3.1.
Изменено в версии 3.12: Эта функция выполняет отложенные вызовы только в основном интерпретаторе.
-
int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)¶
- Часть Stable ABI.
Асинхронно возбуждает исключение в потоке. Аргумент id – это идентификатор целевого потока; exc – объект исключения, которое нужно возбудить. Эта функция не крадёт ссылки на exc. Чтобы предотвратить наивное злоупотребление, необходимо написать собственное C-расширение для её вызова. Должна вызываться с прикреплённым состоянием потока. Возвращает количество изменённых состояний потока; обычно это единица, но будет нулём, если идентификатор потока не найден. Если exc равно
NULL, ожидающее исключение (если есть) для потока очищается. Эта функция не возбуждает исключений.Изменено в версии 3.7: Тип параметра id изменён с long на unsigned long.
API потоков операционной системы¶Operating system thread APIs
-
PYTHREAD_INVALID_THREAD_ID¶
Страж-значение для недопустимого идентификатора потока.
В настоящее время эквивалентно
(unsigned long)-1.
-
unsigned long PyThread_start_new_thread(void (*func)(void*), void *arg)¶
- Часть Stable ABI.
Запускает функцию func в новом потоке с аргументом arg. Полученный поток не предназначен для ожидания завершения.
func не должна быть
NULL, но arg может бытьNULL.При успехе эта функция возвращает идентификатор нового потока; при неудаче возвращает
PYTHREAD_INVALID_THREAD_ID.Вызывающий код не должен удерживать присоединённое состояние потока.
-
unsigned long PyThread_get_thread_ident(void)¶
- Часть Stable ABI.
Возвращает идентификатор текущего потока, который никогда не будет равен нулю.
Эта функция не может завершиться ошибкой, и вызывающему не нужно удерживать присоединённое состояние потока.
См. также
-
PyObject *PyThread_GetInfo(void)¶
- Часть Stable ABI начиная с версии 3.3.
Получает общую информацию о текущем потоке в виде объекта структурной последовательности. Эта информация доступна как
sys.thread_infoв Python.В случае успеха возвращается новая сильная ссылка на информацию о потоке; в случае неудачи возвращается
NULLс установленным исключением.Вызывающий код должен удерживать присоединённое состояние потока.
-
PY_HAVE_THREAD_NATIVE_ID¶
Этот макрос определён, когда система поддерживает нативные идентификаторы потоков.
-
unsigned long PyThread_get_thread_native_id(void)¶
- Часть Stable ABI на платформах с нативными идентификаторами потоков.
Возвращает нативный идентификатор текущего потока, назначенный ядром операционной системы; это значение никогда не бывает меньше нуля.
Эта функция доступна, только если определён
PY_HAVE_THREAD_NATIVE_ID.Эта функция не может завершиться ошибкой, и вызывающему не нужно удерживать присоединённое состояние потока.
См. также
-
void PyThread_exit_thread(void)¶
- Часть Stable ABI.
Завершает текущий поток. Эта функция обычно считается небезопасной, и её следует избегать. Она сохранена исключительно для обратной совместимости.
Эту функцию безопасно вызывать, только если все функции в полном стеке вызовов написаны так, чтобы допускать это безопасно.
Предупреждение
Если текущая система использует потоки POSIX (также известные как «pthreads»), эта функция вызывает pthread_exit(3), которая пытается развернуть стек и вызвать деструкторы C++ в некоторых реализациях libc. Однако, если достигается функция
noexcept, это может завершить процесс. Другие системы, такие как macOS, выполняют развёртывание.В Windows эта функция вызывает
_endthreadex(), которая уничтожает поток без вызова деструкторов C++.В любом случае существует риск повреждения стека потока.
Устарело с версии 3.14.
-
void PyThread_init_thread(void)¶
- Часть Stable ABI.
Инициализирует API
PyThread*. Python выполняет эту функцию автоматически, поэтому нет особой необходимости вызывать её из расширяющего модуля.
-
int PyThread_set_stacksize(size_t size)¶
- Часть Stable ABI.
Устанавливает размер стека текущего потока в size байт.
Эта функция возвращает
0при успехе,-1, если size некорректен, или-2, если система не поддерживает изменение размера стека. Эта функция не устанавливает исключения.Вызывающий код не должен удерживать присоединённое состояние потока.
-
size_t PyThread_get_stacksize(void)¶
- Часть Stable ABI.
Возвращает размер стека текущего потока в байтах или
0, если используется размер стека по умолчанию для системы.Вызывающий код не должен удерживать присоединённое состояние потока.