スレッド状態とグローバルインタープリタロック¶
CPython の フリースレッドビルド を除き、Python インタープリタは一般にスレッドセーフではありません。 マルチスレッドの Python プログラムをサポートするため、グローバルインタープリタロック、または GIL というグローバルなロックがあります。 スレッドは Python オブジェクトにアクセスする前に、このロックを保持していなければなりません。 ロックがなければ、マルチスレッドのプログラムでは単純な操作でも問題が起こりえます。 例えば、2 つのスレッドが同じオブジェクトの参照カウントを同時に増やすと、2 回ではなく 1 回しか増えない可能性があります。
このため、Python オブジェクトの操作や Python の C API の呼び出しを行えるのは、GIL を保持するスレッドだけです。
並行実行を模倣するため、インタープリタはバイトコード命令の間で定期的にスレッドの切り替えを試みます (sys.setswitchinterval() を参照)。
そのため、純粋な Python コードでもスレッドセーフにするにはロックが必要です。
また、ファイルの読み書きなどのブロッキング I/O 操作の間は、グローバルインタープリタロックが解放されます。 C API では スレッド状態をデタッチする ことで行います。
Python インタープリタは、スレッド状態 と呼ばれる PyThreadState データ構造に、スレッドごとの情報を保持します。
各スレッドには PyThreadState へのスレッドローカルなポインターがあります。
このポインターが参照するスレッド状態は、アタッチされている と見なされます。
1 つのスレッドが同時に持てる アタッチされたスレッド状態 は 1 つだけです。 フリースレッドビルドを除けば、スレッド状態がアタッチされていることは通常、GIL を保持していることに相当します。 GIL が有効なビルドでは、スレッド状態のアタッチは GIL を取得できるまでブロックします。 ただし、GIL が無効なビルドでも、スレッド状態をアタッチしておく必要があります。 インタープリタが、どのスレッドが Python オブジェクトにアクセスしうるかを把握するためです。
注釈
フリースレッドビルドでも、スレッド状態のアタッチがブロックすることがあります。 GIL が再び有効になる場合や、ガベージコレクション中などにスレッドが一時停止する場合があるためです。
一般に、Python の C API を使うときは、組み込みやメソッドの実装を含め、常にスレッド状態がアタッチされています。
そのため、自分でスレッド状態を用意する必要はほとんどありません。
スレッド状態がアタッチされていないのは、Py_BEGIN_ALLOW_THREADS ブロック内や新しく作られたスレッドなど、特定の場合だけです。
不確かな場合は、PyThreadState_GetUnchecked() が NULL を返すかどうかを確認してください。
スレッド状態を作成する必要がある場合は、PyThreadState_Ensure() または PyThreadState_EnsureFromView() を使うことを推奨します。
これらの関数がスレッド状態を管理します。
拡張コードからのスレッド状態のデタッチ¶
スレッド状態 を操作する拡張コードの多くは、次の単純な構造を取ります。
// スレッド状態をローカル変数に保存する。
// ... ブロッキング I/O 操作を行う ...
// ローカル変数からスレッド状態を復元する。
この構造は非常に一般的なので、作業を単純にするために2つのマクロが用意されています:
Py_BEGIN_ALLOW_THREADS
... ブロッキング I/O 操作を行う ...
Py_END_ALLOW_THREADS
Py_BEGIN_ALLOW_THREADS マクロは新たなブロックを開始し、隠しローカル変数を宣言します; Py_END_ALLOW_THREADS はブロックを閉じます。
上のブロックは次のコードに展開されます:
PyThreadState *_save;
_save = PyEval_SaveThread();
... ブロッキング I/O 操作を行う ...
PyEval_RestoreThread(_save);
これらの関数は次のように動作します。
スレッド状態がアタッチされているということは、そのインタープリタの GIL を保持しているということです。
デタッチするには PyEval_SaveThread() を呼び出し、結果をローカル変数に保存します。
スレッド状態をデタッチすると GIL が解放され、現在のスレッドがブロッキング I/O を行っている間に、ほかのスレッドがインタープリタにアタッチして実行できるようになります。
I/O 操作が完了したら、PyEval_RestoreThread() を呼び出して元のスレッド状態を再びアタッチします。
この呼び出しは GIL を取得できるまで待機します。
注釈
スレッド状態をデタッチする最も一般的な用途はブロッキング I/O ですが、Python オブジェクトや Python の C API にアクセスしない、実行時間の長いネイティブコードでも有用です。
例えば、標準モジュールの zlib と hashlib は、データの圧縮やハッシュ計算中に スレッド状態 をデタッチします。
フリースレッドビルド では通常 GIL を考慮する必要はありませんが、スレッド状態のデタッチは依然として必要です。 インタープリタは、競合状態の危険なく Python オブジェクトの整合した状態を把握するため、定期的にすべてのスレッドをブロックする必要があるためです。 例えば、現在の CPython はガベージコレクターの実行中、すべてのスレッドを短時間停止します。
警告
スレッド状態のデタッチは、インタープリタの終了処理中に予期しない動作を引き起こす可能性があります。 詳しくは インタープリタの終了処理に関する注意 を参照してください。
API¶
以下のマクロは、通常末尾にセミコロンを付けずに使います; Python ソース配布物内の使用例を見てください。
注釈
これらのマクロは、デッドロックを防ぐために フリースレッドビルド でも必要です。
-
Py_BEGIN_ALLOW_THREADS¶
- This macro is available when compiling for the Stable ABI.
このマクロを展開すると
{ PyThreadState *_save; _save = PyEval_SaveThread();になります。マクロに開き波括弧が入っていることに注意してください; この波括弧は後でPy_END_ALLOW_THREADSマクロと対応させなければなりません。マクロについての詳しい議論は上記を参照してください。
-
Py_END_ALLOW_THREADS¶
- This macro is available when compiling for the Stable ABI.
このマクロを展開すると
PyEval_RestoreThread(_save); }になります。 閉じ波括弧を含むため、事前のPy_BEGIN_ALLOW_THREADSマクロと対応させなければなりません。 このマクロについては上の説明を参照してください。
-
Py_BLOCK_THREADS¶
- This macro is available when compiling for the Stable ABI.
このマクロを展開すると
PyEval_RestoreThread(_save);になります: 閉じ波括弧のないPy_END_ALLOW_THREADSと同じです。
-
Py_UNBLOCK_THREADS¶
- This macro is available when compiling for the Stable ABI.
このマクロを展開すると
_save = PyEval_SaveThread();になります: 開き波括弧のないPy_BEGIN_ALLOW_THREADSと同じです。
外部スレッドからの C API の使用¶
threading モジュールなどの Python の専用 API でスレッドを作成すると、スレッド状態が自動的に関連付けられます。
一方、独自のスレッド管理を行うサードパーティーライブラリなど、ネイティブコードで作成されたスレッドには、アタッチされたスレッド状態がありません。
このようなスレッドから Python コードを呼び出す必要がある場合は、まずスレッド状態を新しく作成してアタッチし、スレッドをインタープリタに登録しなければなりません。 このような呼び出しは、前述のサードパーティーライブラリが提供するコールバック API の一部として行われることがよくあります。
最も簡単な方法は、PyThreadState_Ensure() または PyThreadState_EnsureFromView() を使うことです。
注釈
これらの関数には、対象のインタープリタを指すポインターを引数として渡す必要があります。
このポインターは、スレッドを作成する関数で PyInterpreterGuard_FromCurrent() (PyThreadState_Ensure 用) または PyInterpreterView_FromCurrent() (PyThreadState_EnsureFromView 用) を呼び出すことで取得できます。
ネイティブスレッドライブラリにデータを渡す引数がない場合など、ポインターを利用できないときは、PyInterpreterView_FromMain() でメインインタープリタのビューを取得できます。
ただし、この方法ではコードがサブインタープリタに対応できなくなることに注意してください。
例えば:
// このスレッドを作成した関数での
// PyInterpreterGuard_FromCurrent() の戻り値。
PyInterpreterGuard *guard = thread_data->guard;
// インタープリタのスレッド状態を新しく作成する。
PyThreadStateToken *token = PyThreadState_Ensure(guard);
if (token == NULL) {
PyInterpreterGuard_Close(guard);
return;
}
// 有効なスレッド状態があるので、ここで Python の操作を行う。
result = CallSomeFunction();
// result を評価するか、例外を処理する。
// スレッド状態を解放する。
// ここから先では C API を呼び出してはならない。
PyThreadState_Release(token);
PyInterpreterGuard_Close(guard);
PyThreadState_Ensure を呼び出しても、必ずしもスレッド状態が新しく作成されるとは限りません。
また、PyThreadState_Release を呼び出しても、必ずしもデタッチされるとは限りません。
これらの関数は、すでにアタッチされたスレッド状態を再利用したり、現在のスレッドに以前アタッチされていたスレッド状態を再びアタッチしたりする場合があります。
参考
繰り返しの呼び出しでスレッド状態を再利用する¶
PyThreadState の作成と破棄にはコストがかかり、フリースレッドビルド ではさらに高くなります。
ネイティブのスレッドプールのワーカースレッドなど、インタープリタを何度も呼び出す外部スレッドでは、呼び出しのたびにスレッド状態を作成し、戻るたびに破棄することを避けるべきです。
代わりに、スレッドの開始時、または最初に Python を呼び出したときにスレッド状態を 1 つ用意し、各呼び出しの前後でアタッチとデタッチを行い、スレッドの終了時に一度だけ破棄します。
PyThreadState_New() でスレッド状態を明示的に管理し、PyEval_RestoreThread() と PyEval_SaveThread() でアタッチとデタッチを行います。
この処理は、スレッドのライフサイクルの異なる時点で行う、3 つの段階に分かれます。
スレッドの開始時に、そのスレッドのスレッド状態を 1 つ作成します。
interp は対象のインタープリタです。
スレッドを作成したコードが、スレッド状態をアタッチした状態で PyInterpreterState_Get() などを呼び出して取得しておきます。
PyThreadState *tstate = PyThreadState_New(interp);
その後、Python を呼び出すたびにスレッド状態をアタッチし、その状態を必要とする Python C API を呼び出してから、再びデタッチします。 こうすることで、Python 以外の処理中にスレッドが GIL を保持しないようにします。 Python の呼び出しは、スレッドの存続中に何度も行われる場合があります。
PyEval_RestoreThread(tstate);
result = CallSomeFunction(); /* ここで Python C API を呼び出す */
PyEval_SaveThread();
スレッドが Python を呼び出す必要がなくなったら、スレッド状態を一度だけ破棄します。
PyEval_RestoreThread(tstate);
PyThreadState_Clear(tstate);
PyThreadState_DeleteCurrent();
外部スレッドからの呼び出しに使う汎用の関数 PyThreadState_Ensure() と、従来の PyGILState_Ensure() は、スレッド状態が保持されることを保証 しません。
スレッド状態の寿命は意図的に実装に委ねられているため、対応する取得と解放の組ごとにスレッド状態が作成・破棄される場合があります。
呼び出しをまたいで 1 つのスレッド状態を再利用したい場合は、ここに示したように PyThreadState_New() を使ってください。
外部スレッドを作成したコードは、スレッドが終了する前、かつ Py_FinalizeEx() が呼び出される前に、後始末の手順が実行されるようにしなければなりません。
インタープリタの終了処理が先に始まると、後始末で呼び出す PyEval_RestoreThread() は戻らずにスレッドを停止させます (インタープリタの終了処理に関する注意 を参照)。
後始末を行わずにスレッドが終了すると、スレッド状態はプロセスの終了までリークしたままになります。
スレッド状態のアタッチとデタッチ¶
-
PyThreadStateToken *PyThreadState_Ensure(PyInterpreterGuard *guard)¶
- 次に属します: Stable ABI (バージョン 3.15 より).
スレッドに、guard が保護するインタープリタのスレッド状態をアタッチし、そのインタープリタを安全に呼び出せるようにします。
すでにスレッド状態がアタッチされているスレッドから呼び出しても構いません。 ただし、この呼び出しに対応する
PyThreadState_Release()を後で呼び出す必要があります (つまり、この関数の入れ子の呼び出しは許可されています)。この関数が状態を変更した場合、対応する
PyThreadState_Release()の呼び出しによって元に戻ります。エラー時は、例外を設定 せずに
NULLを返します。 この場合はPyThreadState_Release()を呼び出さないでください。成功時はポインター値を返します。 この値は、対応する
PyThreadState_Release()の呼び出しに渡さなければなりません。この関数が新しい スレッド状態 を作成する条件は、安定した仕様ではなく実装に依存します。 スレッド状態の寿命を厳密に制御する必要がある場合は、
PyThreadState_New()の使用を検討してください。 ただし、バージョンによってスレッド状態の寿命が異なる可能性があるという理由だけで、この関数の使用を避けないでください。 この関数の変更は、後方互換性を保ちながら慎重に行われます。 特に、スレッドローカル変数や同様の状態の保存は、Python のバージョンが変わっても維持されます。この関数が新しいスレッド状態を作成するかどうかの具体的な動作を以下に示します。 ただし、将来変わる可能性があることに注意してください。
まず、アタッチされたスレッド状態があるかどうかを調べます。 ある場合は、そのスレッド状態のインタープリタが guard で保護されたインタープリタと一致するかを調べます。 一致すれば、スレッド状態に
PyThreadState_Ensureの呼び出しで使用中であることを記録して戻ります。アタッチされたスレッド状態がない場合は、現在の OS スレッドが使用したスレッド状態があるかどうかを調べます (
PyGILState_GetThisThreadState()が返すものです)。 ある場合は、そのスレッド状態のインタープリタが guard と一致するかを調べます。 一致すれば、再びアタッチして使用中であることを記録します。上のどちらにも当てはまらない場合は、guard 用のスレッド状態を新しく作成します。 その後、そのスレッド状態をアタッチし、
PyThreadState_Ensureが所有することを記録します。Added in version 3.15.
-
PyThreadStateToken *PyThreadState_EnsureFromView(PyInterpreterView *view)¶
- 次に属します: Stable ABI (バージョン 3.15 より).
view が参照するインタープリタの、アタッチされたスレッド状態を取得します。
動作と戻り値は
PyThreadState_Ensure()と同じです。 さらに、関数が成功した場合は view が参照するインタープリタが暗黙に保護されます。 この保護は、対応するPyThreadState_Release()の呼び出しで解除されます。Added in version 3.15.
-
void PyThreadState_Release(PyThreadStateToken *token)¶
- 次に属します: Stable ABI (バージョン 3.15 より).
PyThreadState_Ensure()またはPyThreadState_EnsureFromView()の呼び出しによる変更を元に戻します。成功した Ensure の呼び出しごとに、その戻り値を token に指定して、必ず一度だけ呼び出さなければなりません。
対応する Ensure の呼び出しの前にスレッド状態がアタッチされていた場合、
PyThreadState_Release()が戻るときには、その状態がアタッチされています。この関数がスレッド状態を削除するかどうかの具体的な動作は、安定した仕様ではなく実装に依存します。
現在、この関数はアタッチされたスレッド状態の内部カウンターを減らします。 カウンターがゼロ未満になると、
Py_FatalError()によって致命的エラーを発生させます。アタッチされたスレッド状態を
PyThreadState_Ensureが所有している場合は、内部カウンターがゼロになるとそのスレッド状態を解放して削除します。 それ以外の場合は、カウンターがゼロになっても何も起こりません。Added in version 3.15.
-
type PyThreadStateToken¶
- 次に属します: Stable ABI (不透明な構造体として) (バージョン 3.15 より).
PyThreadState_Ensure()の呼び出しで取得し、対応するPyThreadState_Release()の呼び出しに渡す不透明なトークンです。
GIL 状態の API¶
以下の API は一般にサブインタープリタに対応しておらず、インタープリタの終了処理中にはプロセスが停止したままになります (インタープリタの終了処理に関する注意 を参照)。 そのため、Python 3.15 で 緩やかに非推奨 となり、代わりに 新しい API の使用を推奨します。
-
type PyGILState_STATE¶
- 次に属します: Stable ABI.
PyGILState_Ensure()が返し、PyGILState_Release()に渡す値の型です。-
enumerator PyGILState_LOCKED¶
PyGILState_Ensure()が呼び出された時点で、すでに GIL を保持していました。
-
enumerator PyGILState_UNLOCKED¶
PyGILState_Ensure()が呼び出された時点では、GIL を保持していませんでした。
-
enumerator PyGILState_LOCKED¶
-
PyGILState_STATE PyGILState_Ensure()¶
- 次に属します: Stable ABI.
Python や アタッチされたスレッド状態 の現在の状態にかかわらず、現在のスレッドで Python C API を呼び出せるようにします。 各呼び出しに対応する
PyGILState_Release()を呼び出す限り、スレッドは何度でもこの関数を呼び出せます。 一般に、PyGILState_Ensure()とPyGILState_Release()の間では、Release()の前にスレッド状態を元に戻す限り、ほかのスレッド関連の API を使っても構いません。 例えば、Py_BEGIN_ALLOW_THREADSとPy_END_ALLOW_THREADSマクロは通常どおり使えます。戻り値は、
PyGILState_Ensure()を呼び出したときの アタッチされたスレッド状態 を表す不透明な「ハンドル」です。 Python を同じ状態に戻すため、PyGILState_Release()に渡さなければなりません。 再帰的な呼び出しは許可されていますが、ハンドルを共有することは できません。PyGILState_Ensure()の呼び出しごとにハンドルを保存し、その呼び出しに対応するPyGILState_Release()に渡す必要があります。この関数が戻るときには スレッド状態がアタッチされており、スレッドは任意の Python コードを呼び出せます。
この関数にはエラーを返す手段がありません。 そのため、エラーは致命的エラーとなる (
SIGABRTを送信してプロセスを異常終了させる。Py_FatalError()を参照) か、インタープリタの終了処理中のように、スレッドが永久にブロックされます。警告
インタープリタの終了処理中に呼び出すと、スレッドが無期限に停止し、デッドロックの原因になる可能性があります。 詳しくは インタープリタの終了処理に関する注意 を参照してください。
また、外部スレッドから使う場合、この関数は一般にサブインタープリタでは動作しません。 どのインタープリタがスレッドを作成したかを知る手段がないため、暗黙にメインインタープリタを選ぶからです。
バージョン 3.14 で変更: インタープリタの終了処理中に呼び出された場合、現在のスレッドを終了させる代わりに、停止したままにするようになりました。
バージョン 3.15 で ソフト非推奨 <Soft deprecated>: 代わりに
PyThreadState_Ensure()またはPyThreadState_EnsureFromView()を使ってください。
-
void PyGILState_Release(PyGILState_STATE)¶
- 次に属します: Stable ABI.
先に取得したリソースを解放します。 呼び出し後の Python の状態は、対応する
PyGILState_Ensure()の呼び出しの前と同じになります (ただし、呼び出し元は通常その状態を把握していないため、GIL 状態の API を使います)。PyGILState_Ensure()を呼び出す場合は、必ず同一スレッド内で対応するPyGILState_Release()を呼び出してください。バージョン 3.15 で ソフト非推奨 <Soft deprecated>: 代わりに
PyThreadState_Release()を使ってください。
-
PyThreadState *PyGILState_GetThisThreadState()¶
- 次に属します: Stable ABI.
このスレッドに最後に アタッチされた スレッド状態 を取得します。 最後のスレッド状態が削除されていれば
NULLを返します。呼び出し元にアタッチされたスレッド状態があれば、それを返します。
言い換えると、
PyGILState_Ensure()が使うスレッド状態を返します。NULLを返す場合、PyGILState_Ensureはスレッド状態を新しく作成します。この関数は失敗しません。
バージョン 3.15 で ソフト非推奨 <Soft deprecated>: 代わりに
PyThreadState_Get()またはPyThreadState_GetUnchecked()を使ってください。
-
int PyGILState_Check()¶
現在のスレッドに アタッチされたスレッド状態 があり、
PyGILState_GetThisThreadState()が返すスレッド状態と一致する場合は1を返します。 呼び出し元にアタッチされたスレッド状態がない場合や、一致しない場合は0を返します。現在の Python プロセスが一度でもサブインタープリタを作成していれば、この関数は 常に
1を返します。主に補助や診断のための関数です。
Added in version 3.4.
バージョン 3.15 で ソフト非推奨 <Soft deprecated>: 代わりに
PyThreadState_GetUnchecked() != NULLを使ってください。
fork() に関する注意¶
スレッドに関するもう 1 つの重要な注意点は、C の fork() 呼び出し時の動作です。
fork() を備えるほとんどのシステムでは、プロセスを fork した後には、fork を呼び出したスレッドだけが存在します。
これは、ロックの扱い方と CPython ランタイムに保存されたすべての状態の両方に、具体的な影響を及ぼします。
「現在の」スレッドだけが残るため、ほかのスレッドが保持していたロックは解放されなくなります。
Python は os.fork() で、内部で使うロックを fork の前に取得し、後で解放することで対処します。
さらに、子プロセスの Lock オブジェクト をすべてリセットします。
Python の拡張や組み込みでは、fork 前の取得や fork 後のリセットが必要な、Python 以外の追加のロックを Python に知らせる方法はありません。
同じ処理を行うには、pthread_atfork() などの OS の機能を使う必要があります。
また、Python の拡張や組み込みで os.fork() を経由せずに fork() を直接呼び出し、その後 Python に戻るか Python を呼び出すと、デッドロックが起こる可能性があります。
Python 内部のロックを保持していたスレッドが、fork 後には存在しなくなるためです。
PyOS_AfterFork_Child() は必要なロックのリセットを試みますが、常にできるとは限りません。
ほかのスレッドがすべて消えるため、それらに対応する CPython ランタイムの状態も適切に後始末する必要があります。
os.fork() はこの処理を行います。
具体的には、現在のインタープリタに属するほかのすべての PyThreadState オブジェクトと、ほかのすべての PyInterpreterState オブジェクトの終了処理を行います。
このことと メインインタープリタ の特殊な性質のため、fork() は、CPython のグローバルなランタイムを最初に初期化した、そのインタープリタの「メイン」スレッドでのみ呼び出すべきです。
直後に exec() を呼び出す場合だけは例外です。
高水準 API¶
マルチスレッドの C 拡張を書くときに最もよく使われる型と関数です。
-
type PyThreadState¶
- 次に属します: Stable ABI (不透明な構造体として).
このデータ構造は、1 つのスレッドの状態を表します。 公開されているデータメンバーは次のものだけです。
-
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 かどうかは、呼び出し元が調べる必要があります。Added in version 3.13: Python 3.5 から 3.12 では、この関数は非公開で、
_PyThreadState_UncheckedGet()という名前でした。
-
PyThreadState *PyThreadState_Swap(PyThreadState *tstate)¶
- 次に属します: Stable ABI.
アタッチされたスレッド状態 を tstate に設定し、呼び出し前にアタッチされていた スレッド状態 を返します。
アタッチされたスレッド状態 がなくても安全に呼び出せます。 その場合は、以前のスレッド状態がなかったことを示す
NULLを返すだけです。注釈
PyGILState_Ensure()と同様に、ランタイムの終了処理中にはスレッドが停止したままになります。
低水準 API¶
-
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 はどのスレッドにも アタッチされていてはなりません。 事前に
PyThreadState_Clear()を呼び出して tstate をリセットしておく必要があります。
-
void PyThreadState_DeleteCurrent(void)¶
アタッチされたスレッド状態 をデタッチし、破棄します。 このスレッド状態は、事前に
PyThreadState_Clear()を呼び出してリセットしておく必要があります。
-
PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate)¶
- 次に属します: Stable ABI (バージョン 3.10 より).
Python のスレッド状態 tstate の現在のフレームを取得します。
強参照 を返します。 現在実行中のフレームがなければ
NULLを返します。PyEval_GetFrame()も参照してください。tstate は
NULLであってはならず、アタッチされていなければなりません。Added in version 3.9.
-
uint64_t PyThreadState_GetID(PyThreadState *tstate)¶
- 次に属します: Stable ABI (バージョン 3.10 より).
Python のスレッド状態 tstate の、一意な スレッド状態 識別子を取得します。
tstate は
NULLであってはならず、アタッチされていなければなりません。Added in version 3.9.
-
PyInterpreterState *PyThreadState_GetInterpreter(PyThreadState *tstate)¶
- 次に属します: Stable ABI (バージョン 3.10 より).
Python のスレッド状態 tstate のインタープリタを取得します。
tstate は
NULLであってはならず、アタッチされていなければなりません。Added in version 3.9.
-
void PyThreadState_EnterTracing(PyThreadState *tstate)¶
Python のスレッド状態 tstate でのトレースとプロファイリングを一時停止します。
再開するには
PyThreadState_LeaveTracing()を使います。Added in version 3.11.
-
void PyThreadState_LeaveTracing(PyThreadState *tstate)¶
PyThreadState_EnterTracing()によって一時停止した、Python のスレッド状態 tstate でのトレースとプロファイリングを再開します。PyEval_SetTrace()とPyEval_SetProfile()も参照してください。Added in version 3.11.
-
int PyUnstable_ThreadState_SetStackProtection(PyThreadState *tstate, void *stack_start_addr, size_t stack_size)¶
- これは Unstable APIです。マイナーリリースで予告なく変更されることがあります。
Python のスレッド状態の、スタック保護の開始アドレスとサイズを設定します。
成功時は
0を返します。 失敗時は例外を設定して-1を返します。CPython は、マシンの実行スタックがオーバーフローに近づいていることを検出すると
RecursionErrorを送出することで、C コードの 再帰を制御 します。 例えばPy_EnterRecursiveCall()を参照してください。 このため、現在のスレッドのスタックの位置を知る必要があり、通常は OS から取得します。 Boost ライブラリのboost::contextのようなコンテキスト切り替え技法でスタックを変更する場合は、PyUnstable_ThreadState_SetStackProtection()を呼び出して CPython に変更を知らせなければなりません。PyUnstable_ThreadState_SetStackProtection()は、スタックを変更する前か後に呼び出してください。 この呼び出しとスタックの変更の間に、ほかの Python C API を呼び出さないでください。この操作を元に戻すには
PyUnstable_ThreadState_ResetStackProtection()を参照してください。Added in version 3.15.
-
void PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate)¶
- これは Unstable APIです。マイナーリリースで予告なく変更されることがあります。
Python のスレッド状態の、スタック保護の開始アドレスとサイズを OS のデフォルト値に戻します。
説明は
PyUnstable_ThreadState_SetStackProtection()を参照してください。Added in version 3.15.
-
PyObject *PyThreadState_GetDict()¶
- 戻り値: 借用参照。 次に属します: Stable ABI.
拡張がスレッド固有の状態情報を保存するための辞書を返します。 各拡張は、一意なキーを使って辞書に状態を保存するべきです。 スレッド状態 が アタッチされていない 場合も呼び出せます。
NULLが返った場合、例外は送出されておらず、呼び出し元はスレッド状態がアタッチされていないと判断するべきです。
-
void PyEval_AcquireThread(PyThreadState *tstate)¶
- 次に属します: Stable ABI.
tstate を現在のスレッドに アタッチ します。 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()はより高レベルな関数で常に (スレッドが初期化されていないときでも) 利用できます。
非同期通知¶
インタプリタのメインスレッドに非同期な通知を行うために提供されている仕組みです。これらの通知は関数ポインタと void ポインタ引数という形態を取ります。
-
int Py_AddPendingCall(int (*func)(void*), void *arg)¶
- 次に属します: Stable ABI.
インタプリタのメインスレッドから関数が呼び出される予定を組みます。成功すると
0が返り、func はメインスレッドの呼び出しキューに詰められます。失敗すると、例外をセットせずに-1が返ります。無事にキューに詰められると、func は いつかは必ず インタプリタのメインスレッドから、arg を引数として呼び出されます。この関数は、通常の実行中の Python コードに対して非同期に呼び出されますが、次の両方の条件に合致したときに呼び出されます:
bytecode 境界上にいるとき、
メインスレッドに スレッド状態がアタッチされている こと (したがって func はすべての C API を使えます)。
func は成功時に
0を返し、失敗時には例外を設定して-1を返さなければなりません。 別の非同期通知を再帰的に処理するために func が中断されることはありませんが、スレッド状態 がデタッチされると、スレッドの切り替えのために中断されることはあります。This function doesn't need an attached thread state. However, to call this function in a subinterpreter, the caller must have an attached thread state. Otherwise, the function func can be scheduled to be called from the wrong interpreter.
警告
これは低水準の関数で、ごく特殊な場合にのみ有用です。 func ができるだけ早く呼び出されるという保証はありません。 メインスレッドがシステムコールを実行中なら、それが戻るまで func は呼び出されません。 一般に、任意の C スレッドから Python コードを呼び出すための関数としては 適していません。 代わりに
PyThreadState_EnsureFromView()を使ってください。Added in version 3.1.
バージョン 3.9 で変更: サブインタープリタでこの関数を呼び出すと、func はメインインタープリタではなく、そのサブインタープリタで呼び出されるようになりました。 サブインタープリタごとに、呼び出しを予定した関数のリストを持つようになりました。
バージョン 3.12 で変更: func は常にメインインタープリタで実行されるようになりました。
-
int Py_MakePendingCalls(void)¶
- 次に属します: Stable ABI.
保留中の呼び出しをすべて実行します。 通常、インタープリタが自動的に実行します。
成功時は
0を返し、失敗時は例外を設定して-1を返します。メインインタープリタのメインスレッドで呼び出されなければ、何もせず
0を返します。 呼び出し元には スレッド状態がアタッチされていなければなりません。Added in version 3.1.
バージョン 3.12 で変更: メインインタープリタの保留中の呼び出しだけを実行するようになりました。
-
int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)¶
- 次に属します: Stable ABI.
スレッドで例外を非同期に送出するように予定します。 そのスレッドに送出予定の例外がすでにあれば、上書きします。
id 引数は対象スレッドの ID で、
PyThread_get_thread_ident()が返すものです。 exc は送出する例外のクラスです。NULLを指定すると、保留中の例外があれば取り消します。対象となったスレッド状態の数を返します。 id が見つかれば通常は
1で、実際には変更されなかった場合でも同じです (指定した exc がすでに保留中だった場合や、exc がNULLで保留中の例外もなかった場合)。 スレッド ID が見つからなければ0を返します。 例外は送出しません。安易な誤用を防ぐため、呼び出すには独自の C 拡張を書く必要があります。 スレッド状態がアタッチされている 状態で呼び出さなければなりません。 この関数は exc への参照を 盗みません。
sleep()などのシステムコールを中断するとは限りません。バージョン 3.7 で変更: id 引数の型が long から unsigned long へ変更されました。
OS スレッドの API¶
-
PYTHREAD_INVALID_THREAD_ID¶
無効なスレッド ID を表す番兵値。
現在は
(unsigned long)-1と等価です。
-
unsigned long PyThread_start_new_thread(void (*func)(void*), void *arg)¶
- 次に属します: Stable ABI.
新しいスレッドで関数 func を引数 arg とともに開始します。 作成したスレッドは join することを想定していません。
func は
NULLであってはなりませんが、arg はNULLでも構いません。成功時は新しいスレッドの識別子を返し、失敗時は
PYTHREAD_INVALID_THREAD_IDを返します。呼び出し元に スレッド状態がアタッチされている 必要はありません。
-
unsigned long PyThread_get_thread_ident(void)¶
- 次に属します: Stable ABI.
現在のスレッドの識別子を返します。 ゼロになることはありません。
この関数は失敗せず、呼び出し元に スレッド状態がアタッチされている 必要もありません。
参考
threading.get_ident()とthreading.Thread.identを使って、Python からこの識別子にアクセスできます。
-
PyObject *PyThread_GetInfo(void)¶
- 次に属します: Stable ABI (バージョン 3.3 より).
Get general information about the current thread in the form of a struct sequence object. This information is accessible as
sys.thread_infoin Python.成功時はスレッド情報への新しい 強参照 を返します。 失敗時は例外を設定して
NULLを返します。呼び出し元には スレッド状態がアタッチされていなければなりません。
-
PY_HAVE_THREAD_NATIVE_ID¶
システムがネイティブスレッド ID をサポートしている場合に定義されるマクロです。
-
unsigned long PyThread_get_thread_native_id(void)¶
- 次に属します: Stable ABI on platforms with native thread IDs.
OS のカーネルが割り当てた、現在のスレッドのネイティブ識別子を取得します。 ゼロ未満になることはありません。
PY_HAVE_THREAD_NATIVE_IDが定義されている場合にのみ利用できます。この関数は失敗せず、呼び出し元に スレッド状態がアタッチされている 必要もありません。
-
void PyThread_exit_thread(void)¶
- 次に属します: Stable ABI.
現在のスレッドを終了させます。 一般に安全ではないとされており、使用を避けるべきです。 後方互換性のためだけに残されています。
呼び出しスタックにあるすべての関数が、この呼び出しを安全に許容できるように書かれている場合にのみ、安全に呼び出せます。
警告
POSIX スレッド (pthreads とも呼ばれます) を使うシステムでは、pthread_exit(3) を呼び出します。 一部の libc 実装では、この関数はスタックを巻き戻して C++ のデストラクターを呼び出そうとします。 ただし、
noexcept関数に到達すると、プロセスを終了させる可能性があります。 macOS など、ほかのシステムでは巻き戻しが行われます。Windows では
_endthreadex()を呼び出し、C++ のデストラクターを呼び出さずにスレッドを終了させます。どの場合も、スレッドのスタックが破損する危険があります。
バージョン 3.14 で非推奨.
-
void PyThread_init_thread(void)¶
- 次に属します: Stable ABI.
PyThread*API を初期化します。 Python が自動的に実行するため、拡張モジュールから呼び出す必要はほとんどありません。
-
int PyThread_set_stacksize(size_t size)¶
- 次に属します: Stable ABI.
Set the stack size of the current thread to size bytes.
成功時は
0、size が無効な場合は-1、システムがスタックサイズの変更に対応していない場合は-2を返します。 例外は設定しません。呼び出し元に スレッド状態がアタッチされている 必要はありません。
-
size_t PyThread_get_stacksize(void)¶
- 次に属します: Stable ABI.
Return the stack size of the current thread in bytes, or
0if the system's default stack size is in use.呼び出し元に スレッド状態がアタッチされている 必要はありません。