Когда должен вызываться PyEval_InitThreads?

Я немного не понимаю, когда мне звонить PyEval_InitThreads. В общем, я понимаю, что PyEval_InitThreads должен вызываться всякий раз, когда используется поток, отличный от Python (т. е. поток, порожденный в модуле расширения).

Однако я запутался, если PyEval_InitThreads предназначен для программ C, которые встраивают интерпретатор Python, или программ Python, которые импортируют модули расширения C, или и того, и другого.

Итак, если я напишу модуль расширения C, который будет запускать внутренний поток, нужно ли мне вызывать PyEval_InitThreads при инициализации модуля?

Кроме того, PyEval_InitThreads неявно получает глобальную блокировку интерпретатора. Таким образом, после вызова PyEval_InitThreads, предположительно, GIL должен быть освобожден, иначе возникнет взаимоблокировка. Итак, как снять блокировку? После прочтения документации PyEval_ReleaseLock() кажется, что чтобы выпустить GIL. Однако на практике, если я использую следующий код в модуле расширения C:

   PyEval_InitThreads();
   PyEval_ReleaseLock();

... затем во время выполнения Python прерывается:

Fatal Python error: drop_gil: GIL is not locked

Итак, как вы выпускаете GIL после его приобретения с помощью PyEval_InitThreads?


person Channel72    schedule 17.02.2013    source источник
comment
Попробуйте без PyEval_ReleaseLock(). GIL приобретен по уважительной причине; выпуск его перед вызовом других функций C API из Python приведет к сбою.   -  person Armin Rigo    schedule 17.02.2013


Ответы (1)


Большинству приложений вообще не нужно знать о PyEval_InitThreads().

Его следует использовать только в том случае, если ваше встраиваемое приложение или модуль расширения будут выполнять вызовы Python C API из более чем одного потока, созданного им самим вне Python.

Не вызывайте PyEval_ReleaseLock() в любом потоке, который позже будет выполнять вызовы Python C API (если только вы не получите его повторно до этого). В этом случае вам следует использовать макросы Py_BEGIN_ALLOW_THREADS и Py_END_ALLOW_THREADS.

person gps    schedule 17.02.2013
comment
Я не понимаю этот ответ. Предполагая, что вы встраиваете Python в программу на C и у вас есть 20 рабочих потоков, кто должен вызывать PyEval_InitThreads, и как каждый рабочий процесс освобождает блокировку, когда он занят другими делами, чтобы другие потоки, которым нужно выполнять некоторую работу Python, могли получить GIL ? - person DougN; 20.02.2013
comment
@DougN, да, я согласен. Ответ расплывчатый (как, к сожалению, и сами документы Python) - person Charles Salvia; 22.02.2013
comment
Если вы встраиваете Python в программу на C, вызовите ее один раз для всей программы, поскольку вы инициализируете встроенный интерпретатор Python, прежде чем он выполнит ваш первый код Python. - person gps; 22.02.2013