Документация Python неофициальный перевод
Содержание страницы

Состояния потоков и глобальная блокировка интерпретатора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 в настоящее время приостанавливает все потоки на короткое время во время работы сборщика мусора.

Предупреждение

Отсоединение состояния потока может привести к непредсказуемому поведению при завершении работы интерпретатора. Подробнее см. Предостережения по поводу завершения выполнения.

APIAPIs

Следующие макросы обычно используются без точки с запятой в конце; примеры использования можно найти в дистрибутиве исходного кода 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 без открывающей фигурной скобки и объявления переменной.

Потоки, созданные не из PythonNon-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 окажется висячим указателем!

Устаревший APILegacy 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() будет вызван сразу после.

Высокоуровневые APIHigh-level APIs

Это наиболее часто используемые типы и функции при написании многопоточных расширений на C.

type PyThreadState
Часть Limited API (как непрозрачная структура).

Эта структура данных представляет состояние одного потока. Единственный открытый элемент данных:

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, указывая, что предыдущего состояния потока не было.

См. также

PyEval_ReleaseThread()

Примечание

Аналогично PyGILState_Ensure(), эта функция приведёт к зависанию потока, если среда выполнения завершает работу.

API состояния GILGIL-state APIs

Следующие функции используют локальное хранилище потока и несовместимы с подынтерпретаторами:

type PyGILState_STATE
Часть Stable ABI.

Тип значения, возвращаемого PyGILState_Ensure() и передаваемого в PyGILState_Release().

enumerator PyGILState_LOCKED

GIL уже был захвачен, когда была вызвана PyGILState_Ensure().

enumerator PyGILState_UNLOCKED

GIL не был захвачен, когда была вызвана PyGILState_Ensure().

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().

См. также

PyThreadState_Get()

int PyGILState_Check()

Возвращает 1, если текущий поток удерживает GIL, и 0 в противном случае. Эту функцию можно вызывать из любого потока в любое время. Только если её состояние потока было инициализировано через PyGILState_Ensure(), она вернёт 1. В основном это вспомогательная/диагностическая функция. Она может быть полезна, например, в контекстах колбэков или функций выделения памяти, когда знание того, что GIL заблокирован, может позволить вызывающему выполнять чувствительные действия или иначе вести себя по-другому.

Примечание

Если текущий процесс Python когда-либо создавал подынтерпретатор, эта функция будет всегда возвращать 1. Для большинства случаев предпочтительнее использовать PyThreadState_GetUnchecked().

Добавлено в версии 3.4.

Низкоуровневые APILow-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 должна возвращать 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.

Возвращает идентификатор текущего потока, который никогда не будет равен нулю.

Эта функция не может завершиться ошибкой, и вызывающему не нужно удерживать присоединённое состояние потока.

См. также

threading.get_ident()

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.

Эта функция не может завершиться ошибкой, и вызывающему не нужно удерживать присоединённое состояние потока.

См. также

threading.get_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, если используется размер стека по умолчанию для системы.

Вызывающий код не должен удерживать присоединённое состояние потока.