初期化 (initialization)、終了処理 (finalization)、スレッド — Python 2.7ja1 documentation

### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python 2.7ja1 documentation »
- Python/C API リファレンスマニュアル »

# 初期化 (initialization)、終了処理 (finalization)、スレッド

## インタプリタの初期化と終了処理

void `Py_Initialize`()

  Python インタプリタを初期化します。 Python の埋め込みを行うアプリケーションでは、他のあらゆる Python/C API を使用するよりも前にこの関数を呼び出さねばなりません。ただし、 `Py_SetProgramName()`, `PyEval_InitThreads()`, `PyEval_ReleaseLock()`, および `PyEval_AcquireLock()` は例外です。この関数はロード済みモジュールのテーブル (`sys.modules`) を初期化し、基盤となるモジュール群、 `__builtin__`, `__main__`, `sys` を生成します。また、モジュール検索パス (`sys.path`) も初期化します。 `sys.argv` の設定は行いません。設定するには、 `PySys_SetArgvEx()` を使ってください。この関数を (`Py_Finalize()` を呼ばずに) 再度呼び出しても何も行いません。戻り値はありません。初期化が失敗すれば、それは致命的なエラーです。

void `Py_InitializeEx`(int initsigs)

  initsigs に1を指定すれば `Py_Initialize()` と同じ処理を実行しますが、 Python埋め込みアプリケーションでは initsigs を0として初期化時にシグナルハンドラの登録をスキップすることができます。

  バージョン 2.4 で追加.

int `Py_IsInitialized`()

  Python インタプリタがすでに初期化済みの場合に真 (非ゼロ) を返し、そうでない場合には偽 (ゼロ) を返します。 `Py_Finalize()` を呼び出すと、次に `Py_Initialize()` を呼び出すまでこの関数は偽を返します。

void `Py_Finalize`()

  `Py_Initialize()` とそれ以後の Python/C API 関数で行った全ての初期化処理を取り消し、最後の `Py_Initialize()` 呼び出し以後に Python インタプリタが生成した全てのサブインタプリタ (sub-interpreter, 下記の `Py_NewInterpreter()` を参照) を消去します。理想的な状況では、この関数によって Python インタプリタが確保したメモリは全て解放されます。この関数を (`Py_Initialize()` を呼ばずに) 再度呼び出しても何も行いません。戻り値はありません。 終了処理中のエラーは無視されます。

  この関数が提供されている理由はいくつかあります。 Python の埋め込みを行っているアプリケーションでは、アプリケーションを再起動することなく Python を再起動したいことがあります。また、動的ロード可能イブラリ (あるいは DLL) から Python インタプリタをロードするアプリケーションでは、DLL をアンロードする前に Python が確保したメモリを全て解放したいと考えるかもしれません。アプリケーション内で起きているメモリリークを追跡する際に、開発者は Python が確保したメモリをアプリケーションの終了前に解放させたいと思う場合もあります。

  バグおよび注意事項: モジュールやモジュール内のオブジェクトはランダムな順番で削除されます。このため、他のオブジェクト(関数オブジェクトも含みます) やモジュールに依存するデストラクタ (`__del__()` メソッド) が失敗してしまうことがあります。動的にロードされるようになっている拡張モジュールが Python によってロードされていた場合、アンロードされません。 Python が確保したメモリがわずかながら解放されないかもしれません (メモリリークを発見したら、どうか報告してください)。オブジェクト間の循環参照に捕捉されているメモリは解放されないことがあります。拡張モジュールが確保したメモリは解放されないことがあります。拡張モジュールによっては、初期化ルーチンを 2 度以上呼び出すと正しく動作しないことがあります。 こうした状況は、 `Py_Initialize()` や `Py_Finalize()` を 2 度以上呼び出すと起こり得ます。

## プロセスワイドのパラメータ

void `Py_SetProgramName`(char *name)

  この関数を呼び出すなら、最初に `Py_Initialize()` を呼び出すよりも前に呼び出さねばなりません。この関数はインタプリタにプログラムの `main()` 関数に指定した `argv[0]` 引数の値を教えます。この引数値は、 `Py_GetPath()` や、以下に示すその他の関数が、インタプリタの実行可能形式から Python ランタイムライブラリへの相対パスを取得するために使われます。デフォルトの値は `'python'` です。引数はゼロ終端されたキャラクタ文字列で、静的な記憶領域に入っていなければならず、その内容はプログラムの実行中に変更してはなりません。 Python インタプリタ内のコードで、この記憶領域の内容を変更するものは一切ありません。

char* `Py_GetProgramName`()

  `Py_SetProgramName()` で設定されたプログラム名か、デフォルトのプログラム名を返します。関数が返す文字列ポインタは静的な記憶領域を返します。関数の呼び出し側はこの値を変更できません。

char* `Py_GetPrefix`()

  プラットフォーム非依存のファイル群がインストールされている場所である prefix を返します。この値は `Py_SetProgramName()` でセットされたプログラム名やいくつかの環境変数をもとに、数々の複雑な規則から導出されます。例えば、プログラム名が `'/usr/local/bin/python'` の場合、prefix は `'/usr/local'` になります。関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値はトップレベルの `Makefile` に指定されている変数 prefix や、ビルド値に configure スクリプトに指定した --prefix 引数に対応しています。この値は Python コードからは `sys.prefix` として利用できます。これはUnixでのみ有用です。次に説明する関数も参照してください。

char* `Py_GetExecPrefix`()

  プラットフォーム 依存 のファイルがインストールされている場所である exec-prefix を返します。この値は `Py_SetProgramName()` でセットされたプログラム名やいくつかの環境変数をもとに、数々の複雑な規則から導出されます。例えば、プログラム名が `'/usr/local/bin/python'` の場合、exec-prefix は `'/usr/local'` になります。関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値はトップレベルの `Makefile` に指定されている変数 exec_prefix や、ビルド値に configure スクリプトに指定した --exec-prefix 引数に対応しています。この値は Python コードからは `sys.exec_prefix` として利用できます。 Unixのみで有用です。

  背景: プラットフォーム依存のファイル (実行形式や共有ライブラリ) が別のディレクトリツリー内にインストールされている場合、 exec-prefix は prefix と異なります。典型的なインストール形態では、プラットフォーム非依存のファイルが `/usr/local` に収められる一方、プラットフォーム依存のファイルは `/usr/local/plat` サブツリーに収められます。

  一般的に、プラットフォームとは、ハードウェアとソフトウェアファミリの組み合わせを指します。例えば、 Solaris 2.x を動作させている Sparc マシンは全て同じプラットフォームであるとみなしますが、Solaris 2.x を動作させている Intel マシンは違うプラットフォームになりますし、同じ Intel マシンでも Linux を動作させているならまた別のプラットフォームです。一般的には、同じオペレーティングシステムでも、メジャーリビジョンの違うものは異なるプラットフォームです。非 Unix のオペレーティングシステムの場合は話はまた別です; 非 Unix のシステムでは、インストール方法はとても異なっていて、 prefix や exec-prefix には意味がなく、空文字列が設定されています。コンパイル済みの Python バイトコードはプラットフォームに依存しないので注意してください (ただし、どのバージョンの Python でコンパイルされたかには依存します!)。

  システム管理者は、 mount や automount プログラムを使って、各プラットフォーム用の `/usr/local/plat` を異なったファイルシステムに置き、プラットフォーム間で `/usr/local` を共有するための設定方法を知っているでしょう。

char* `Py_GetProgramFullPath`()

  Python 実行可能形式の完全なプログラム名を返します; この値はデフォルトのモジュール検索パスを (前述の `Py_SetProgramName()` で設定された) プログラム名から導出する際に副作用的に計算されます。関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値は Python コードからは `sys.executable` として利用できます。

char* `Py_GetPath`()

  デフォルトのモジュール検索パスを返します; パスは (上の `Py_SetProgramName()` で設定された) プログラム名と、いくつかの環境変数から計算されます。戻り値となる文字列は、プラットフォーム依存のパス区切り文字で分割された一連のディレクトリ名からなります。区切り文字は Unix と Mac OS X では `':'`, Windows では `';'` です。関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。 `sys.path` はインタプリタによってこの値で初期化され、その後にモジュールをロードする際の検索パスを変更するために修正することが可能で、たいていそうされます。

const char* `Py_GetVersion`()

  Python インタプリタのバージョンを返します。バージョンは、次のような形式の文字列です。

      "1.5 (#67, Dec 31 1997, 22:34:28) [GCC 2.7.2.2]"

  第一ワード (最初のスペース文字まで) は、現在の Python のバージョンです; 最初の三文字は、ピリオドで区切られたメジャーバージョンとマイナーバージョンです。関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値は Python コードからは `sys.version` として利用できます。

const char* `Py_GetPlatform`()

  現在のプラットフォームのプラットフォーム識別文字列を返します。 Unixでは、オペレーティングシステムの “公式の” 名前を小文字に変換し、後ろにメジャーリビジョン番号を付けた構成になっています。例えば Solaris 2.x は、SunOS 5.x, としても知られていますが、 `'sunos5'` になります。Mac OS X では `'darwin'` です。 Windows では `'win'` です。関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値は Python コードからは `sys.platform` として利用できます。

const char* `Py_GetCopyright`()

  現在の Python バージョンに対する公式の著作権表示文字列、例えば `'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'` を返します。

  関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値は Python コードからは `sys.copyright` として利用できます。

const char* `Py_GetCompiler`()

  現在使っているバージョンの Python をビルドする際に用いたコンパイラを示す文字列を、角括弧で囲った文字列を返します。例えば:

      "[GCC 2.7.2.2]"

  になります。

  関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値は Python コードからは `sys.version` の一部として取り出せます。

const char* `Py_GetBuildInfo`()

  現在使っている Python インタプリタインスタンスの、シーケンス番号とビルド日時に関する情報を返します。例えば

      "#67, Aug  1 1997, 22:34:28"

  になります。

  関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。この値は Python コードからは `sys.version` の一部として取り出せます。

void `PySys_SetArgvEx`(int argc, char **argv, int updatepath)

  argc および argv に基づいて `sys.argv` を設定します。これらの引数はプログラムの `main()` に渡した引数に似ていますが、最初の要素が Python インタプリタの宿主となっている実行形式の名前ではなく、実行されるスクリプト名を参照しなければならない点が違います。実行するスクリプトがない場合、 argv の最初の要素は空文字列にしてもかまいません。この関数が `sys.argv` の初期化に失敗した場合、致命的エラーを `Py_FatalError()` で知らせます。

  updatepath が 0 の場合、ここまでの動作がこの関数がすることの全てです。 updatepath が 0 でない場合、この関数は `sys.path` を以下のアルゴリズムに基づいて修正します:

  - 存在するスクリプトの名前が `argv[0]` に渡された場合、そのスクリプトがある場所の絶対パスを `sys.path` の先頭に追加します。
  - それ以外の場合(argc が 0 だったり、 `argv[0]` が存在するファイル名をさしていない場合)、 `sys.path` の先頭に空の文字列を追加します。これは現在の作業ディレクトリ (`"."`) を先頭に追加するのと同じです。

  ノート

  Python インタプリタを、単一のスクリプトを実行する以外の目的で埋め込むアプリケーションは、 updatepath に 0 を渡して必要なら自分で `sys.path` を更新することをおすすめします。 CVE-2008-5983 を参照してください。

  2.6.6 より前のバージョンでは、 `PySys_SetArgv()` を呼出たあとに同じ事を手動で `sys.path` の先頭の要素を取り除くことで実現できます。例えば、次のようにします。

      PyRun_SimpleString("import sys; sys.path.pop(0)\n");

  バージョン 2.6.6 で追加.

void `PySys_SetArgv`(int argc, char **argv)

  `PySys_SetArgvEx()` の updatepath に 1 を設定したのと同じように動作します。

void `Py_SetPythonHome`(char *home)

  Python の標準ライブラリがある、デフォルトの “home” ディレクトリを設定します。引数の文字列の意味については `PYTHONHOME` を参照してください。

  引数は静的なストレージに置かれてプログラム実行中に書き換えられないようなゼロ終端の文字列であるべきです。 Python インタプリタはこのストレージの内容を変更しません。

char* `Py_GetPythonHome`()

  前回の `Py_SetPythonHome()` 呼び出しで設定されたデフォルトの “home” か、 `PYTHONHOME` 環境変数が設定されていればその値を返します。

## スレッド状態 (thread state) とグローバルインタプリタロック (global interpreter lock)

Python インタプリタは完全にはスレッドセーフではありません。マルチスレッドの Python プログラムをサポートするために、グローバルインタプリタロック(global interpreter lock, GIL) と呼ばれるグローバルなロックが存在していて、現在のスレッドが Python オブジェクトに安全にアクセスする前に必ずロックを獲得しなければならなくなっています。ロック機構がなければ、単純な操作でさえ、マルチスレッドプログラムの実行に問題を引き起こす可能性があります。たとえば、二つのスレッドが同じオブジェクトの参照カウントを同時にインクリメントすると、結果的に参照カウントは二回でなく一回だけしかインクリメントされないかもしれません。

このため、 GIL を獲得したスレッドだけが Python オブジェクトを操作したり、 Python/C API 関数を呼び出したりできるというルールがあります。並行処理をエミュレートするために、インタプリタは定期的にロックを解放したり獲得したりします。 (`sys.setcheckinterval()` を参照) このロックはブロックが起こりうる I/O 操作の付近でも解放・獲得され、 I/O を要求するスレッドが I/O 操作の完了を待つ間、他のスレッドが動作できるようにしています。

Python インタプリタはスレッドごとに必要な情報を `PyThreadState` と呼ばれるデータ構造の中に保存します。そしてグローバル変数として現在の `PyThreadState` を指すポインタを1つ持ちます。このグローバル変数は `PyThreadState_Get()` を使って取得できます。

### 拡張コード内で GIL を解放する

GIL を操作するほとんどのコードは、次のような単純な構造になります。

    スレッド状態をローカル変数に保存する。
    GILを解放する。
    ...ブロックが起きるような何らかの I/O 操作...
    GILを獲得する。
    ローカル変数からスレッド状態を回復する。

この構造は非常に一般的なので、作業を単純にするために2つのマクロが用意されています:

    Py_BEGIN_ALLOW_THREADS
    ...ブロックが起きるような何らかの I/O 操作...
    Py_END_ALLOW_THREADS

`Py_BEGIN_ALLOW_THREADS` マクロは新たなブロックを開始し、隠しローカル変数を宣言します; `Py_END_ALLOW_THREADS` はブロックを閉じます。 Python をスレッドサポートなしでコンパイルしたときでもこの2つのマクロは利用可能です。 (単に、空行に展開されます)

スレッドサポートが有効になっている場合、上記のブロックは以下のようなコードに展開されます:

    PyThreadState *_save;

    _save = PyEval_SaveThread();
    ...ブロックが起きるような何らかの I/O 操作...
    PyEval_RestoreThread(_save);

これらの関数の動作を説明します。 GIL は現在のスレッド状態を指すポインタを保護するために使われます。ロックを解放してスレッド状態を退避する際、ロックを解放する前に現在のスレッド状態ポインタを取得しておかなければなりません (他のスレッドがすぐさまロックを獲得して、自らのスレッド状態をグローバル変数に保存してしまうかもしれないからです)。逆に、ロックを獲得してスレッド状態を復帰する際には、グローバル変数にスレッド状態ポインタを保存する前にロックを獲得しておかなければなりません。

ノート

GIL を解放するのはほとんどがシステムのI/O関数を呼び出す時ですが、メモリバッファに対する圧縮や暗号化のように、 Python のオブジェクトにアクセスしない長時間かかる計算処理を呼び出すときも GIL を解放することは有益です。例えば、 `zlib` や `hashlib` モジュールは圧縮やハッシュ計算の前に GIL を開放します。

### Python 以外で作られたスレッド

Python API を通して作られたスレッド (`threading` モジュールなど) では自動的にスレッド状態が割り当てられて、上記のコードは正しく動きます。しかし、(自前でスレッド管理を行う外部のライブラリなどにより)C言語でスレッドを生成した場合、そのスレッドには GIL がなく、スレッド状態データ構造体もないことに注意する必要があります。

このようなスレッドから Python コードを呼び出す必要がある場合 (外部のライブラリからコールバックするAPIなどがよくある例です)、 Python/C API を呼び出す前に、スレッド状態データ構造体を生成し、 GIL を獲得し、スレッド状態ポインタを保存することで、スレッドをインタプリタに登録しなければなりません。スレッドが作業を終えたら、スレッド状態ポインタをリセットして、ロックを解放し、最後にスレッド状態データ構造体のメモリを解放しなければなりません。

`PyGILState_Ensure()` と `PyGILState_Release()` はこの処理を自動的に行います。 Cのスレッドから Python を呼び出す典型的な方法は以下のとおりです。

    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();

    /* Perform Python actions here. */
    result = CallSomeFunction();
    /* evaluate result or handle exception */

    /* Release the thread. No Python API allowed beyond this point. */
    PyGILState_Release(gstate);

`PyGILState_*()` 関数は、(`Py_Initialize()` によって自動的に作られる) グローバルインタプリタ1つだけが存在すると仮定する事に気をつけて下さい。 Python は (`Py_NewInterpreter()` を使って) 追加のインタプリタを作成できることに変わりはありませんが、複数インタプリタと `PyGILState_*()` API を混ぜて使うことはサポートされていません。

注意しないといけないもう一つの重要な点は、 C の `fork()` を呼び出した時の動作です。ほとんどの `fork()` を持っているシステムでは、fork されたプロセスには fork を実行したスレッドしか存在しません。これは、別のスレッドに取得されたロックがずっと開放されないことを意味します。 Python は fork する前にロックを取得し、その後に fork を開放することでこの問題を解決しています。加えて、子プロセスではすべての Lock オブジェクト をリセットします。 Python を拡張したり埋め込んだりしている場合、 Python に fork 前に取得したり fork 後に開放しなければならない追加の (Python 以外の) ロックを Python に教える手段がありません。 Python と同じことを実現するには、 `posix_atfork()` のようなOSの機能を使う必要があります。加えて、Python を拡張したり埋め込んだりしているときに、 `os.fork()` を通してではなく直接 `fork()` を呼び出すと、fork後に失われるスレッドに取得されていた Python の内部ロックのためにデッドロックが発生するかもしれません。 `PyOS_AfterFork()` は必要なロックのリセットを試みますが、いつでもそれが可能とは限りません。

### 高レベルAPI

C拡張を書いたりPythonインタプリタを埋め込むときに最も一般的に使われる型や関数は次のとおりです。

`PyInterpreterState`

  このデータ構造体は、協調動作する多数のスレッド間で共有されている状態を表現します。同じインタプリタに属するスレッドはモジュール管理情報やその他いくつかの内部的な情報を共有しています。この構造体には公開 (public) のメンバはありません。

  異なるインタプリタに属するスレッド間では、利用可能なメモリ、開かれているファイルデスクリプタなどといったプロセス状態を除いて、初期状態では何も共有されていません。 GILもまた、スレッドがどのインタプリタに属しているかに関わらずすべてのスレッドで共有されています。

`PyThreadState`

  単一のスレッドの状態を表現する表現するデータ構造体です。スレッドのインタプリタ状態を指すポインタ `PyInterpreterState *` `interp` だけが公開されているデータメンバです。

void `PyEval_InitThreads`()

  GIL を初期化し、獲得します。この関数は、主スレッドが第二のスレッドを生成する以前や、 `PyEval_ReleaseLock()` や `PyEval_ReleaseThread(tstate)` といった他のスレッド操作に入るよりも前に呼び出されるようにしておかなければなりません。 `PyEval_SaveThread()`, `PyEval_RestoreThread()` の前に呼び出す必要はありません。

  二度目に呼び出すと何も行いません。この関数を `Py_Initialize()` の前に呼び出しても安全です。

  ノート

  主スレッドしか存在しないのであれば、GIL操作は必要ありません。これはよくある状況ですし (ほとんどの Python プログラムはスレッドを使いません)、ロック操作はインタプリタをごくわずかに低速化します。従って、初期状態ではロックは生成されません。ロックを使わない状況は、すでにロックを獲得している状況と同じです: 単一のスレッドしかなければ、オブジェクトへのアクセスは全て安全です。従って、この関数がGILを初期化すると、同時にロックを獲得するようになっています。Python の `_thread` モジュールは、新たなスレッドを作成する前に、ロックが存在するか、あるいはまだ作成されていないかを調べ、 `PyEval_InitThreads()` を呼び出します。この関数から処理が戻った場合、ロックが作成され、呼び出し元スレッドがそのロックを獲得している事が保証されています。

  どのスレッドが現在 GIL を (存在する場合) 持っているか分からない時にこの関数を使うのは安全では ありません 。

  この関数はコンパイル時にスレッドサポートを無効化すると利用できません。

int `PyEval_ThreadsInitialized`()

  `PyEval_InitThreads()` をすでに呼び出している場合は真 (非ゼロ) を返します。この関数は、GILを獲得せずに呼び出すことができますので、シングルスレッドで実行している場合にはロック関連のAPI呼び出しを避けるために使うことができます。この関数はコンパイル時にスレッドサポートを無効化すると利用できません。

  バージョン 2.4 で追加.

PyThreadState* `PyEval_SaveThread`()

  (GIL が生成されていて、スレッドサポートが有効の場合) GILを解放して、スレッド状態を NULL にし、以前のスレッド状態 (NULL にはなりません) を返します。ロックがすでに生成されている場合、現在のスレッドがロックを獲得していなければなりません。 (この関数はコンパイル時にスレッドサポートが無効にされていても利用できます。)

void `PyEval_RestoreThread`(PyThreadState *tstate)

  (GIL が生成されていて、スレッドサポートが有効の場合) GIL を獲得して、現在のスレッド状態を tstate に設定します。 tstate は NULL であってはなりません。 GIL が生成されていて、この関数を呼び出したスレッドがすでにロックを獲得している場合、デッドロックに陥ります。 (この関数はコンパイル時にスレッドサポートが無効にされていても利用できます。)

PyThreadState* `PyThreadState_Get`()

  現在のスレッド状態を返します。GIL を保持していなければなりません。現在のスレッド状態が NULL なら、(呼び出し側が NULL チェックをしなくてすむように) この関数は致命的エラーを起こすようになっています。

PyThreadState* `PyThreadState_Swap`(PyThreadState *tstate)

  現在のスレッド状態を tstate に指定したスレッド状態と入れ変えます。 tstate は NULL の場合があります。 GIL を保持していなければならず、開放しません。

void `PyEval_ReInitThreads`()

  この関数は `PyOS_AfterFork()` から呼び出され、新しい子プロセスが、子プロセス内で実行していないスレッドが持っているロックを持たないようにします。

以下の関数はスレッドローカルストレージを利用していて、サブインタプリタとの互換性がありません。

PyGILState_STATE `PyGILState_Ensure`()

  Pythonの状態やGILに関わらず、実行中スレッドでPython C APIの呼び出しが可能となるようにします。この関数はスレッド内で何度でも呼び出すことができますが、必ず全ての呼び出しに対応して `PyGILState_Release()` を呼び出す必要があります。

  通常、 `PyGILState_Ensure()` 呼び出しと `PyGILState_Release()` 呼び出しの間でこれ以外のスレッド関連API を使用することができますが、Release()の前にスレッド状態は復元されていなければなりません。例えば、通常の `Py_BEGIN_ALLOW_THREADS` マクロと `Py_END_ALLOW_THREADS` は使用することができます。

  戻り値は `PyGILState_Ensure()` 呼び出し時のスレッド状態を隠蔽した”ハンドル”で、 `PyGILState_Release()` に渡してPythonを同じ状態に保たなければなりません。再起呼び出しも可能ですが、ハンドルを共有することは できません - それぞれの `PyGILState_Ensure()` 呼び出しでハンドルを保存し、対応する `PyGILState_Release()` 呼び出しで渡してください。

  関数から復帰したとき、実行中のスレッドはGILを所有していて、任意の Python コードを実行できます。処理の失敗は致命的なエラーです。

  バージョン 2.3 で追加.

void `PyGILState_Release`(PyGILState_STATE)

  獲得したすべてのリソースを開放します。この関数を呼び出すと、Pythonの状態は対応する `PyGILState_Ensure()` を呼び出す前と同じとなります。(通常、この状態は呼び出し元でははわかりませんので、GILState APIを利用するようにしてください。）

  `PyGILState_Ensure()` を呼び出す場合は、必ず同一スレッド内で対応する `PyGILState_Release()` を呼び出してください。

  バージョン 2.3 で追加.

以下のマクロは、通常末尾にセミコロンを付けずに使います; Python ソース配布物内の使用例を見てください。

`Py_BEGIN_ALLOW_THREADS`

  このマクロを展開すると `{ PyThreadState *_save; _save = PyEval_SaveThread();` になります。マクロに開き波括弧が入っていることに注意してください; この波括弧は後で `Py_END_ALLOW_THREADS` マクロと対応させなければなりません。マクロについての詳しい議論は上記を参照してください。コンパイル時にスレッドサポートが無効化されていると何も行いません。

`Py_END_ALLOW_THREADS`

  このマクロを展開すると `PyEval_RestoreThread(_save); }` になります。マクロに開き波括弧が入っていることに注意してください; この波括弧は事前の `Py_BEGIN_ALLOW_THREADS` マクロと対応していなければなりません。マクロについての詳しい議論は上記を参照してください。コンパイル時にスレッドサポートが無効化されていると何も行いません。

`Py_BLOCK_THREADS`

  このマクロを展開すると `PyEval_RestoreThread(_save);` になります: 閉じ波括弧のない `Py_END_ALLOW_THREADS` と同じです。コンパイル時にスレッドサポートが無効化されていると何も行いません。

`Py_UNBLOCK_THREADS`

  このマクロを展開すると `_save = PyEval_SaveThread();` になります: 開き波括弧のない `Py_BEGIN_ALLOW_THREADS` と同じです。コンパイル時にスレッドサポートが無効化されていると何も行いません。

### 低レベルAPI

以下の全ての関数はコンパイル時にスレッドサポートが有効になっている時だけ利用でき、呼び出すのはGILがすでに作成されている場合だけにしなくてはなりません。

PyInterpreterState* `PyInterpreterState_New`()

  新しいインタプリタ状態オブジェクトを生成します。 GIL を保持しておく必要はありませんが、この関数を次々に呼び出す必要がある場合には保持しておいたほうがよいでしょう。

void `PyInterpreterState_Clear`(PyInterpreterState *interp)

  インタプリタ状態オブジェクト内の全ての情報をリセットします。 GIL を保持していなければなりません。

void `PyInterpreterState_Delete`(PyInterpreterState *interp)

  インタプリタ状態オブジェクトを破壊します。GIL を保持しておく必要はありません。インタプリタ状態は `PyInterpreterState_Clear()` であらかじめリセットしておかなければなりません。

PyThreadState* `PyThreadState_New`(PyInterpreterState *interp)

  指定したインタプリタオブジェクトに属する新たなスレッド状態オブジェクトを生成します。 GIL を保持しておく必要はありませんが、この関数を次々に呼び出す必要がある場合には保持しておいたほうがよいでしょう。

void `PyThreadState_Clear`(PyThreadState *tstate)

  スレッド状態オブジェクト内の全ての情報をリセットします。 GIL を保持していなければなりません。

void `PyThreadState_Delete`(PyThreadState *tstate)

  スレッド状態オブジェクトを破壊します。GIL を保持する必要はありません。スレッド状態は `PyThreadState_Clear()` であらかじめリセットしておかなければなりません。

PyObject* `PyThreadState_GetDict`()
  Return value: Borrowed reference.

  拡張モジュールがスレッド固有の状態情報を保存できるような辞書を返します。各々の拡張モジュールが辞書に状態情報を保存するためには唯一のキーを使わねばなりません。現在のスレッド状態がない時にこの関数を呼び出してもかまいません。この関数が NULL を返す場合、例外はまったく送出されず、呼び出し側は現在のスレッド状態が利用できないと考えねばなりません。

  バージョン 2.3 で変更: 以前は、現在のスレッドがアクティブなときのみ呼び出せるようになっており、 NULL は例外が送出されたことを意味していました.

int `PyThreadState_SetAsyncExc`(long id, PyObject *exc)

  スレッド内で非同期的に例外を送出します。 id 引数はターゲットとなるスレッドのスレッド id です; exc は送出する例外オブジェクトです。この関数は exc に対する参照を一切盗み取りません。素朴な間違いを防ぐため、この関数を呼び出すには独自に C 拡張モジュールを書かねばなりません。 GIL を保持した状態で呼び出さなければなりません。

  変更を受けたスレッド状態の数を返します; これは普通は1ですが、スレッドidが見つからなかった場合は0になります。もし exc が `NULL` であれば、そのスレッドで保留されている例外があればクリアします。この場合は例外は発生しません。

  バージョン 2.3 で追加.

void `PyEval_AcquireThread`(PyThreadState *tstate)

  GIL を獲得し、現在のスレッド状態を tstate に設定します。 tstate は NULL であってはなりません。ロックはあらかじめ作成されていなければなりません。この関数を呼び出したスレッドがすでにロックを獲得している場合、デッドロックに陥ります。

  `PyEval_RestoreThread()` はより高レベルな関数で常に(スレッドサポートが無効な場合やスレッドが初期化されていない場合でも)利用できます。

void `PyEval_ReleaseThread`(PyThreadState *tstate)

  現在のスレッド状態をリセットして NULL にし、GIL を解放します。ロックはあらかじめ作成されていなければならず、かつ現在のスレッドが保持していなければなりません。 tstate は NULL であってはなりませんが、その値が現在のスレッド状態を表現しているかどうかを調べるためにだけ使われます — もしそうでなければ、致命的エラーが報告されます。

  `PyEval_SaveThread()` はより高レベルな関数で常に(スレッドサポートが無効な場合やスレッドが初期化されていない場合でも)利用できます。

void `PyEval_AcquireLock`()

  GILを獲得します。ロックは前もって作成されていなければなりません。この関数を呼び出したスレッドがすでにロックを獲得している場合、デッドロックに陥ります。

  警告

  この関数は現在のスレッド状態を変更しません。代わりに `PyEval_RestoreThread()` か `PyEval_AcquireThread()` を利用してください。

void `PyEval_ReleaseLock`()

  GILを解放します。ロックは前もって作成されていなければなりません。

  警告

  この関数は現在のスレッド状態を変更しません。代わりに `PyEval_SaveThread()` か `PyEval_ReleaseThread()` を利用してください。

## サブインタプリタサポート

ほとんどの場合は埋め込む Python インタプリタは1つだけですが、いくつかの場合に同一プロセス内、あるいは同一スレッド内で、複数の独立したインタプリタを作成する必要があります。サブインタプリタはこれを可能にします。 `PyThreadState_Swap()` 関数を使ってサブインタプリタを切り替えることができます。以下の関数を使ってサブインタプリタの作成と削除を行えます。

PyThreadState* `Py_NewInterpreter`()

  新しいサブインタプリタ (sub-interpreter) を生成します。サブインタプリタとは、(ほぼ完全に) 個別に分割された Python コードの実行環境です。特に、新しいサブインタプリタは、 import されるモジュール全てについて個別のバージョンを持ち、これには基盤となるモジュール `__builtin__`, `__main__` および `sys` も含まれます。ロード済みのモジュールからなるテーブル (`sys.modules`) およびモジュール検索パス (`sys.path`) もサブインタプリタ毎に別個のものになります。新たなサブインタプリタ環境には `sys.argv` 変数がありません。また、サブインタプリタは新たな標準 I/O ストリーム `sys.stdin`, `sys.stdout`, `sys.stderr` を持ちます (とはいえ、これらのストリームは根底にある C ライブラリの同じ `FILE` 構造体を参照しています)。

  戻り値は、新たなサブインタプリタが生成したスレッド状態 (thread state) オブジェクトのうち、最初のものを指しています。このスレッド状態が現在のスレッド状態 (current thread state) になります。実際のスレッドが生成されるわけではないので注意してください; 下記のスレッド状態に関する議論を参照してください。新たなインタプリタの生成に失敗すると、 NULL を返します; 例外状態はセットされませんが、これは例外状態が現在のスレッド状態に保存されることになっていて、現在のスレッド状態なるものが存在しないことがあるからです。 (他の Python/C API 関数のように、この関数を呼び出す前にはGILが保持されていなければならず、関数が処理を戻した際にも保持されたままになります; しかし、他の Python/C API 関数とは違い、関数から戻ったときの現在のスレッド状態が関数に入るときと同じとは限らないので注意してください)。

  拡張モジュールは以下のような形で (サブ) インタプリタ間で共有されます: ある特定の拡張モジュールを最初に import すると、モジュールを通常通りに初期化し、そのモジュールの辞書の (浅い) コピーをしまい込んでおきます。他の (サブ) インタプリタが同じ拡張モジュールを import すると、新たなモジュールを初期化し、先ほどのコピーの内容で辞書の値を埋めます; 拡張モジュールの `init` 関数は呼び出されません。この挙動は、 `Py_Finalize()` および `Py_Initialize()` を呼び出してインタプリタを完全に再初期化した後に拡張モジュールを import した際の挙動とは異なるので注意してください; 再初期化後に import を行うと、拡張モジュールの `initmodule` は再度 呼び出されます 。

void `Py_EndInterpreter`(PyThreadState *tstate)

  指定されたスレッド状態 tstate で表現される (サブ) インタプリタを抹消します。 tstate は現在のスレッド状態でなければなりません。下記のスレッド状態に関する議論を参照してください。関数呼び出しが戻ったとき、現在のスレッド状態は NULL になっています。このインタプリタに関連付けられた全てのスレッド状態は抹消されます。 (この関数を呼び出す前にはGILを保持しておかねばならず、ロックは関数が戻ったときも保持されています。) `Py_Finalize()` は、その時点で明示的に抹消されていない全てのサブインタプリタを抹消します。

### バグと注意事項

サブインタプリタ (とメインインタプリタ) は同じプロセスの一部分なので、インタプリタ間の隔離は完璧ではありません — 例えば、 `os.close()` のような低レベルのファイル操作を使うと、 (偶然なり故意なりに) 互いのインタプリタ下にある開かれたファイルに影響を及ぼせてしまいます。拡張モジュールを (サブ) インタプリタ間で共有する方法のせいで、拡張モジュールによっては正しく動作しないかもしれません; 拡張モジュールが (静的な) グローバル変数を利用している場合や、拡張モジュールが初期化後に自身のモジュール辞書を操作する場合には特にそうです。一つのサブインタプリタで生成されたオブジェクトは他のサブインタプリタの名前空間への挿入が可能です; ユーザ定義関数、メソッド、インスタンスおよびクラスをサブインタプリタをサブインタプリタ間で共有しないように十分注意してください。というのは、これらの共有オブジェクトが実行した import 文は間違った (サブ) インタプリタのロード済みモジュール辞書に影響を及ぼす場合があるからです。

サブインタプリタを `PyGILState_*()` API と組み合わせるのが難しいことにも注意してください。これらのAPIはPythonのスレッド状態とOSレベルスレッドが1対1で対応していることを前提にしていて、サブインタプリタが存在するとその前提が崩れるからです。対応する `PyGILState_Ensure()` と `PyGILState_Release()` の呼び出しのペアの間では、サブインタプリタの切り替えを行わないことを強く推奨します。さらに、(`ctypes` のような)これらのAPIを使ってPythonの外で作られたスレッドから Pythonコードを実行している拡張モジュールはサブインタプリタを使うと壊れる可能性があります。

## 非同期通知

メインのインタプリタスレッドへの非同期通知機構が提供されています。この通知は関数ポインタと void 引数の形をしています。

各チェックインターバルにおいて、GILがリリースされて再取得されるときに、 Python はそのような提供された関数を呼び出します。この関数は例えば非同期IOハンドラなどが利用できます。通知はワーカースレッドなどからスケジュールされ、実際の呼び出しはメインスレッドで最初の、GILを所有していて任意の Python API 呼び出しが可能なタイミングで実行されます。

int `Py_AddPendingCall`(int (*func)(void *), void *arg)

  Python のメインスレッドへの通知を登録します。成功した場合、 func は引数 arg と共に、最初の適切なタイミングで呼び出されます。 func は GIL を取得した状態で呼び出されるので、任意の Python API を利用することができ、オブジェクトの属性にIOの完了を知らせるなど、任意の動作をすることができます。通知関数は成功したときには 0 を、例外を通知するときには -1 を返さなければなりません。通知関数は他の通知関数を再帰的に実行するために割り込まれることはありませんが、たとえばPythonコードをコールバックしたときにGILを開放して他のスレッドに切り替えられる可能性はあります。

  この関数は成功して通知関数がスケジュールされたときは 0 を返します。それ以外の場合、たとえば通知バッファがいっぱいのときは、例外を設定せずに -1 を返します。

  この関数はどのスレッドからでも、 Python スレッドでもそれ以外のシステムスレッドからでも呼び出すことができます。 Python スレッドから呼び出される場合は、GILを確保していてもいなくてもかまいません。

  バージョン 2.7 で追加.

## プロファイルとトレース (profiling and tracing)

Python インタプリタは、プロファイル: 分析 (profile) や実行のトレース: 追跡 (trace) といった機能を組み込むために低水準のサポートを提供しています。このサポートは、プロファイルやデバッグ、適用範囲分析 (coverage analysis) ツールなどに使われます。

Python 2.2 になってから、この機能の実装は実質的に作り直され、 C から呼び出すためのインタフェースが追加されました。この C インタフェースは、プロファイルやトレース作業時に、 Python レベルの呼び出し可能オブジェクトが呼び出されることによるオーバヘッドを避け、直接 C 関数呼び出しが行えるようにしています。プロファイルやトレース機能の本質的な特性は変わっていません; インタフェースではとレース関数をスレッドごとにインストールでき、トレース関数に報告される基本イベント (basic event) は以前のバージョンにおいて Python レベルのトレース関数で報告されていたものと同じです。

int `(*Py_tracefunc)`(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)

  `PyEval_SetProfile()` および `PyEval_SetTrace()` を使って登録できるトレース関数の形式です。最初のパラメタはオブジェクトで、登録関数に obj として渡されます。 frame はイベントが属している実行フレームオブジェクトで、 what は定数 `PyTrace_CALL`, `PyTrace_EXCEPTION`, `PyTrace_LINE`, `PyTrace_RETURN`, `PyTrace_C_CALL`, `PyTrace_C_EXCEPTION`, あるいは `PyTrace_C_RETURN` のいずれかで、 arg は what の値によって以下のように異なります:

  what の値 | arg の意味
  --- | ---
  `PyTrace_CALL` | 常に NULL です。
  `PyTrace_EXCEPTION` | `sys.exc_info()` の返す例外情報です。
  `PyTrace_LINE` | 常に NULL です。
  `PyTrace_RETURN` | 呼び出し側に返される予定の値か、例外によって関数を抜ける場合は NULL です。
  `PyTrace_C_CALL` | 呼び出される関数オブジェクト
  `PyTrace_C_EXCEPTION` | 呼び出された関数オブジェクト
  `PyTrace_C_RETURN` | 呼び出された関数オブジェクト

int `PyTrace_CALL`

  関数やメソッドが新たに呼び出されたり、ジェネレータが新たなエントリの処理に入ったことを報告する際の、 `Py_tracefunc` の what の値です。イテレータやジェネレータ関数の生成は、対応するフレーム内の Python バイトコードに制御の委譲 (control transfer) が起こらないため報告されないので注意してください。

int `PyTrace_EXCEPTION`

  例外が送出された際の `Py_tracefunc` の what の値です。現在実行されているフレームで例外がセットされ、何らかのバイトコードが処理された後に、 what にこの値がセットされた状態でコールバック関数が呼び出されます。

  この結果、例外の伝播によって Python が呼び出しスタックを逆戻りする際に、各フレームから処理が戻るごとにコールバック関数が呼び出されます。トレース関数だけがこれらのイベントを受け取ります; プロファイラはこの種のイベントを必要としません。

int `PyTrace_LINE`

  行番号イベントを報告するときに (プロファイル関数ではなく) トレース関数の what パラメタとして渡す値です。

int `PyTrace_RETURN`

  関数呼び出しが例外の伝播なしに返るときに `Py_tracefunc` 関数の what パラメタとして渡す値です。

int `PyTrace_C_CALL`

  C関数を呼び出す直前に `Py_tracefunc` 関数の what パラメタとして渡す値です。

int `PyTrace_C_EXCEPTION`

  C関数が例外を送出したときに `Py_tracefunc` 関数の what パラメタとして渡す値です。

int `PyTrace_C_RETURN`

  C関数から戻るときに `Py_tracefunc` 関数の what パラメタとして渡す値です。

void `PyEval_SetProfile`(Py_tracefunc func, PyObject *obj)

  プロファイル関数を func に設定します。 obj パラメタは関数の第一パラメタとして渡され、何らかの Python オブジェクトかまたは NULL になります。プロファイル関数がスレッド状態を維持する必要があるなら、各々のスレッドに異なる obj を使うことで、状態を記憶しておく便利でスレッドセーフな場所を提供できます。プロファイル関数は、モニタされているイベントのうち、行番号イベントを除く全てのイベントに対して呼び出されます。

void `PyEval_SetTrace`(Py_tracefunc func, PyObject *obj)

  トレース関数を func にセットします。 `PyEval_SetProfile()` に似ていますが、トレース関数は行番号イベントを受け取る点が違います。

## 高度なデバッガサポート (advanced debugger support)

以下の関数は高度なデバッグツールでの使用のためだけのものです。

PyInterpreterState* `PyInterpreterState_Head`()

  インタプリタ状態オブジェクトからなるリストのうち、先頭にあるものを返します。

  バージョン 2.2 で追加.

PyInterpreterState* `PyInterpreterState_Next`(PyInterpreterState *interp)

  インタプリタ状態オブジェクトからなるリストのうち、 interp の次にあるものを返します。

  バージョン 2.2 で追加.

PyThreadState * `PyInterpreterState_ThreadHead`(PyInterpreterState *interp)

  インタプリタ interp に関連付けられているスレッドからなるリストのうち、先頭にある `PyThreadState` オブジェクトを返します。

  バージョン 2.2 で追加.

PyThreadState* `PyThreadState_Next`(PyThreadState *tstate)

  tstate と同じ `PyInterpreterState` オブジェクトに属しているスレッド状態オブジェクトのうち、 tstate の次にあるものを返します。

  バージョン 2.2 で追加.

### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python 2.7ja1 documentation »
- Python/C API リファレンスマニュアル »