2013-02-17 7 views
5

私はPyEval_InitThreadsと呼ぶはずです。一般に、私はPyEval_InitThreadsは、非Pythonスレッド(つまり、拡張モジュール内で生成されたスレッド)が使用されるたびに呼び出さなければならないことを理解しています。PyEval_InitThreadsはいつ呼び出されるのですか?

しかし、PyEval_InitThreadsがPythonインタプリタを埋め込んだCプログラム、またはC拡張モジュールを読み込むPythonプログラム、あるいはその両方の場合は、私は混乱します。

内部でスレッドを起動するC拡張モジュールを作成する場合、モジュールを初期化するときにPyEval_InitThreadsを呼び出す必要がありますか?

また、PyEval_InitThreadsimplicitly acquires the Global Interpreter Lockもあります。したがって、PyEval_InitThreadsを呼び出した後、おそらくGILはにリリースされなければならないか、デッドロックが発生します。では、どうやってロックを解除しますか?ドキュメントを読んだ後、PyEval_ReleaseLock()はGILをリリースする方法のようです。しかし、実際には、私はC拡張モジュールに次のコードを使用している場合:

PyEval_InitThreads(); 
    PyEval_ReleaseLock(); 

を...そして、実行時にPythonがで中止されます:それでは、どのように取得した後にGILを解放しない

Fatal Python error: drop_gil: GIL is not locked 

それはPyEval_InitThreadsと?

+0

'PyEval_ReleaseLock()'を使わずに試してみてください。 GILは正当な理由のために取得されます。 Pythonから他のC API関数を呼び出す前にそれを解放すると、クラッシュすることになります。 –

答えて

3

ほとんどのアプリケーションでは、PyEval_InitThreads()について一切知る必要はありません。

埋め込みアプリケーションまたは拡張モジュールが、複数のスレッドからPython C API呼び出しを作成する場合は、がPythonの外部にあるを生成した場合のみ使用する必要があります。

PyEval_ReleaseLock()は、後でPython C API呼び出しを行うスレッドで呼び出さないでください(それらの前に再度取得しない限り)。その場合は、代わりに実際にPy_BEGIN_ALLOW_THREADSPy_END_ALLOW_THREADSのマクロを使用する必要があります。

+1

私はこの答えを理解していません。あなたがCプログラムにPythonを埋め込み、PyEval_InitThreadsを呼び出す必要があるワーカースレッドが20個あるとし、各作業者が他の作業をしている間にどのようにロックを解放すれば、Pythonの仕事をしなければならない他のスレッドがGIL ? – DougN

+0

@DougN、はい私は同意します。答えはあいまいです(残念なことにPythonのドキュメント自体です) –

+2

CのプログラムをPythonに埋め込んでいる場合は、最初のPythonコードを実行する前に、組み込みのPythonインタプリタを初期化するときにプログラム全体を一度呼び出してください。 – gps