#
8. 初期化 (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_SetArgv()` を使ってください。 この関数を (`Py_Finalize()` を 呼ばずに) 再度呼び出しても何も行いません。 戻り値はありません; 初期化が失敗すれば、それは致命的なエラーです。

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 度以上呼び出すと起こり得ます。

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 関数のように、 この関数を呼び出す前にはグローバルインタプリタロック (global interpreter lock) が保持されていなければならず、関数が 処理を戻した際にも保持されたままになります; しかし、 他の Python/C API 関数とは違い、関数から戻ったときの現在のスレッド状態 が関数に入るときと同じとは限らないので注意してください)。

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

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

void `Py_EndInterpreter`( | PyThreadState *tstate)

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

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` として利用できます。 Unixのみで有用です。

char* `Py_GetPath`( | )

  デフォルトモジュール検索パスを返します; パスは (上の `Py_SetProgramName()` で設定された) プログラム名と、 いくつかの環境変数から計算されます。戻り値となる文字列は、 プラットフォーム依存のパスデリミタ文字で分割された一連の ディレクトリ名からなります。デリミタ文字は Unixでは"`:`"、 Windows では"`;`" 、Macintosh では "`\n`" (ASCII 改行文字) です。関数が返す文字列ポインタは静的な記憶領域を返します; 関数の呼び出し側はこの値を変更できません。 この値は Python コードからはリスト `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'` になります。Macintosh では `'mac'` です。 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` の一部として 取り出せます。

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

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