初期化、ファイナライズ、およびスレッド—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/2.7/c-api/init
移動先:案内検索

初期化、ファイナライズ、およびスレッド

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

void Py_Initialize()
Pythonインタープリターを初期化します。 Pythonを組み込んだアプリケーションでは、他のPython / CAPI関数を使用する前にこれを呼び出す必要があります。 Py_SetProgramName()Py_SetPythonHome()PyEval_InitThreads()PyEval_ReleaseLock()、および Pyval )。 これにより、ロードされたモジュール(sys.modules)のテーブルが初期化され、基本モジュール __ builtin ____ main __ 、および sys が作成されます。 また、モジュール検索パス(sys.path)を初期化します。 sys.argvは設定されません。 そのためには PySys_SetArgvEx()を使用してください。 これは、( Py_Finalize()を最初に呼び出さずに)2回目に呼び出された場合はノーオペレーションです。 戻り値はありません。 初期化が失敗した場合、致命的なエラーになります。
void Py_InitializeEx(int initsigs)

この関数は、 initsigs1の場合、 Py_Initialize()のように機能します。 initsigs0の場合、シグナルハンドラーの初期化登録をスキップします。これは、Pythonが組み込まれている場合に役立つことがあります。

バージョン2.4の新機能。

int Py_IsInitialized()
Pythonインタープリターが初期化されている場合はtrue(ゼロ以外)を返し、そうでない場合はfalse(ゼロ)を返します。 Py_Finalize()が呼び出された後、 Py_Initialize()が再度呼び出されるまで、これはfalseを返します。
void Py_Finalize()

Py_Initialize()によって行われたすべての初期化とその後のPython / C API関数の使用を元に戻し、作成されてまだ破棄されていないすべてのサブインタープリター(以下の Py_NewInterpreter()を参照)を破棄します。 Py_Initialize()の最後の呼び出し以降。 理想的には、これによりPythonインタープリターによって割り当てられたすべてのメモリが解放されます。 これは、2回目に呼び出された場合(最初に Py_Initialize()を再度呼び出さずに)、何も実行されません。 戻り値はありません。 ファイナライズ中のエラーは無視されます。

この機能は、いくつかの理由で提供されています。 埋め込みアプリケーションは、アプリケーション自体を再起動せずにPythonを再起動したい場合があります。 動的にロード可能なライブラリ(またはDLL)からPythonインタプリタをロードしたアプリケーションは、DLLをアンロードする前に、Pythonによって割り当てられたすべてのメモリを解放したい場合があります。 アプリケーションでのメモリリークのハント中に、開発者はアプリケーションを終了する前にPythonによって割り当てられたすべてのメモリを解放したい場合があります。

バグと警告:モジュールとモジュール内のオブジェクトの破棄はランダムな順序で行われます。 これにより、デストラクタ(__del__()メソッド)が他のオブジェクト(関数でさえ)またはモジュールに依存している場合に失敗する可能性があります。 Pythonによってロードされた動的にロードされた拡張モジュールはアンロードされません。 Pythonインタープリターによって割り当てられた少量のメモリが解放されない場合があります(リークを見つけた場合は、報告してください)。 オブジェクト間の循環参照に拘束されているメモリは解放されません。 拡張モジュールによって割り当てられた一部のメモリは解放されない場合があります。 一部の拡張機能は、初期化ルーチンが複数回呼び出された場合に正しく機能しない可能性があります。 これは、アプリケーションが Py_Initialize()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()
インストールされているプラットフォームに依存しないファイルのプレフィックスを返します。 これは、 Py_SetProgramName()で設定されたプログラム名といくつかの環境変数からのいくつかの複雑なルールから導き出されます。 たとえば、プログラム名が'/usr/local/bin/python'の場合、プレフィックスは'/usr/local'です。 返された文字列は静的ストレージを指します。 呼び出し元はその値を変更しないでください。 これは、ビルド時の configure スクリプトのトップレベルMakefileprefix 変数と--prefix引数に対応します。 この値は、Pythonコードでsys.prefixとして使用できます。 Unixでのみ役立ちます。 次の関数も参照してください。
char *Py_GetExecPrefix()

インストールされているプラットフォーム依存ファイルの exec-prefix を返します。 これは、 Py_SetProgramName()で設定されたプログラム名といくつかの環境変数からのいくつかの複雑なルールから導き出されます。 たとえば、プログラム名が'/usr/local/bin/python'の場合、execプレフィックスは'/usr/local'です。 返された文字列は静的ストレージを指します。 呼び出し元はその値を変更しないでください。 これは、ビルド時のトップレベルMakefileexec_prefix 変数および configure スクリプトの--exec-prefix引数に対応します。 この値は、Pythonコードでsys.exec_prefixとして使用できます。 Unixでのみ役立ちます。

背景:プラットフォームに依存するファイル(実行可能ファイルや共有ライブラリなど)が別のディレクトリツリーにインストールされている場合、exec-prefixはプレフィックスとは異なります。 通常のインストールでは、プラットフォームに依存するファイルは/usr/local/platサブツリーにインストールされ、プラットフォームに依存しないファイルは/usr/localにインストールされます。

一般的に言えば、プラットフォームはハードウェアとソフトウェアのファミリの組み合わせです。 Solaris 2.xオペレーティングシステムを実行しているSparcマシンは同じプラットフォームと見なされますが、Solaris 2.xを実行しているIntelマシンは別のプラットフォームであり、Linuxを実行しているIntelマシンはさらに別のプラットフォームです。 同じオペレーティングシステムの異なるメジャーリビジョンも、通常、異なるプラットフォームを形成します。 非Unixオペレーティングシステムは別の話です。 これらのシステムでのインストール戦略は非常に異なるため、プレフィックスとexec-prefixは無意味であり、空の文字列に設定されます。 コンパイルされたPythonバイトコードファイルはプラットフォームに依存しないことに注意してください(ただし、コンパイルされたPythonバージョンからは独立していません!)。

システム管理者は、/usr/local/platをプラットフォームごとに異なるファイルシステムとして、プラットフォーム間で/usr/localを共有するように mount または automount プログラムを構成する方法を知っています。

char *Py_GetProgramFullPath()
Python実行可能ファイルの完全なプログラム名を返します。 これは、プログラム名(上記の Py_SetProgramName()で設定)からデフォルトのモジュール検索パスを導出することの副作用として計算されます。 返された文字列は静的ストレージを指します。 呼び出し元はその値を変更しないでください。 この値は、Pythonコードでsys.executableとして使用できます。
char *Py_GetPath()
デフォルトのモジュール検索パスを返します。 これは、プログラム名(上記の Py_SetProgramName()で設定)といくつかの環境変数から計算されます。 返される文字列は、プラットフォームに依存する区切り文字で区切られた一連のディレクトリ名で構成されます。 区切り文字は、UnixおよびMac OSXでは':'、Windowsでは';'です。 返された文字列は静的ストレージを指します。 呼び出し元はその値を変更しないでください。 リスト sys.path は、インタープリターの起動時にこの値で初期化されます。 モジュールをロードするための検索パスを変更するために、後で変更することができます(通常は変更されます)。
const char *Py_GetVersion()

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

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

最初の単語(最初のスペース文字まで)は現在のPythonバージョンです。 最初の3文字は、ピリオドで区切られたメジャーバージョンとマイナーバージョンです。 返された文字列は静的ストレージを指します。 呼び出し元はその値を変更しないでください。 この値は、Pythonコードでsys.versionとして使用できます。

const char *Py_GetPlatform()
現在のプラットフォームのプラットフォーム識別子を返します。 Unixでは、これはオペレーティングシステムの「正式な」名前から形成され、小文字に変換され、その後にメジャーリビジョン番号が続きます。 たとえば、SunOS5.xとしても知られているSolaris2.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]"

返された文字列は静的ストレージを指します。 呼び出し元はその値を変更しないでください。 この値は、変数sys.versionの一部としてPythonコードで使用できます。

const char *Py_GetBuildInfo()

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

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

返された文字列は静的ストレージを指します。 呼び出し元はその値を変更しないでください。 この値は、変数sys.versionの一部としてPythonコードで使用できます。

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

argcargv に基づいて sys.argv を設定します。 これらのパラメーターは、プログラムのmain()関数に渡されるパラメーターと似ていますが、最初のエントリがPythonインタープリターをホストする実行可能ファイルではなく、実行されるスクリプトファイルを参照する必要がある点が異なります。 実行されるスクリプトがない場合、 argv の最初のエントリは空の文字列である可能性があります。 この関数が sys.argv の初期化に失敗した場合、 Py_FatalError()を使用して致命的な状態が通知されます。

updatepath がゼロの場合、これが関数が実行するすべてです。 updatepath がゼロ以外の場合、関数は次のアルゴリズムに従って sys.path も変更します。

  • 既存のスクリプトの名前がargv[0]で渡される場合、スクリプトが配置されているディレクトリの絶対パスが sys.path の前に付加されます。

  • それ以外の場合(つまり、 argc が0の場合、またはargv[0]が既存のファイル名を指していない場合)、 sys.path の前に空の文字列が追加されます。現在の作業ディレクトリ(".")の先頭に追加するのと同じです。

ノート

単一のスクリプトを実行する以外の目的でPythonインタープリターを埋め込むアプリケーションは、0updatepath として渡し、必要に応じて 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)
この関数は、 updatepath1に設定された PySys_SetArgvEx()のように機能します。
void Py_SetPythonHome(char *home)

デフォルトの「ホーム」ディレクトリ、つまり標準のPythonライブラリの場所を設定します。 引数文字列の意味については、 PYTHONHOME を参照してください。

引数は、静的ストレージ内のゼロで終了する文字列を指している必要があります。この文字列の内容は、プログラムの実行中に変更されません。 Pythonインタープリターのコードは、このストレージの内容を変更しません。

char *Py_GetPythonHome()
デフォルトの「ホーム」、つまり、 Py_SetPythonHome()の前回の呼び出しで設定された値、または PYTHONHOME 環境変数の値を返します。が設定されます。


スレッドの状態とグローバルインタープリターロック

Pythonインタープリターは完全にスレッドセーフではありません。 マルチスレッドのPythonプログラムをサポートするために、グローバルインタープリターロックまたは GIL と呼ばれるグローバルロックがあります。これは、Pythonオブジェクトに安全にアクセスする前に、現在のスレッドによって保持される必要があります。 。 ロックがないと、最も単純な操作でもマルチスレッドプログラムで問題が発生する可能性があります。たとえば、2つのスレッドが同じオブジェクトの参照カウントを同時にインクリメントすると、参照カウントが2回ではなく1回だけインクリメントされる可能性があります。

したがって、 GIL を取得したスレッドのみがPythonオブジェクトを操作したり、Python / CAPI関数を呼び出したりできるというルールが存在します。 実行の並行性をエミュレートするために、インタープリターは定期的にスレッドの切り替えを試みます( sys.setcheckinterval()を参照)。 ロックは、ファイルの読み取りや書き込みなどのI / O操作をブロックする可能性がある場合にも解放されるため、その間に他のPythonスレッドを実行できます。

Pythonインタープリターは、 PyThreadState と呼ばれるデータ構造内にスレッド固有の簿記情報を保持します。 現在の PyThreadState を指すグローバル変数も1つあります。これは、 PyThreadState_Get()を使用して取得できます。

拡張コードからGILを解放する

GIL を操作するほとんどの拡張コードは、次の単純な構造を持っています。

Save the thread state in a local variable.
Release the global interpreter lock.
... Do some blocking I/O operation ...
Reacquire the global interpreter lock.
Restore the thread state from the local variable.

これは非常に一般的であるため、単純化するために1対のマクロが存在します。

Py_BEGIN_ALLOW_THREADS
... Do some blocking I/O operation ...
Py_END_ALLOW_THREADS

Py_BEGIN_ALLOW_THREADS マクロは、新しいブロックを開き、非表示のローカル変数を宣言します。 Py_END_ALLOW_THREADS マクロはブロックを閉じます。 これらの2つのマクロは、Pythonがスレッドサポートなしでコンパイルされている場合でも使用できます(単に空の展開があります)。

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

PyThreadState *_save;

_save = PyEval_SaveThread();
...Do some blocking I/O operation...
PyEval_RestoreThread(_save);

これらの関数のしくみは次のとおりです。グローバルインタープリターロックは、現在のスレッド状態へのポインターを保護するために使用されます。 ロックを解放してスレッド状態を保存する場合、ロックが解放される前に現在のスレッド状態ポインターを取得する必要があります(別のスレッドがすぐにロックを取得し、独自のスレッド状態をグローバル変数に格納できるため)。 逆に、ロックを取得してスレッド状態を復元する場合は、スレッド状態ポインタを格納する前にロックを取得する必要があります。

ノート

システムI / O関数の呼び出しは、GILを解放するための最も一般的な使用例ですが、メモリバッファー上で動作する圧縮関数や暗号化関数など、Pythonオブジェクトへのアクセスを必要としない長時間実行の計算を呼び出す前にも役立ちます。 たとえば、標準の zlib および hashlib モジュールは、データを圧縮またはハッシュするときにGILを解放します。


Python以外で作成されたスレッド

専用のPythonAPI( threading モジュールなど)を使用してスレッドを作成すると、スレッドの状態が自動的にスレッドに関連付けられるため、上記のコードは正しいものになります。 ただし、スレッドがCから作成された場合(たとえば、独自のスレッド管理を備えたサードパーティライブラリによって)、スレッドはGILを保持せず、スレッド状態構造もありません。

これらのスレッドからPythonコードを呼び出す必要がある場合(多くの場合、これは前述のサードパーティライブラリによって提供されるコールバックAPIの一部になります)、最初にスレッド状態データ構造を作成してこれらのスレッドをインタープリターに登録し、次にPython / C APIの使用を開始する前に、GILを実行し、最後にスレッド状態ポインターを格納します。 完了したら、スレッド状態ポインターをリセットし、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_*()関数は、グローバルインタープリターが1つしかないことを前提としていることに注意してください( Py_Initialize()によって自動的に作成されます)。 Pythonは追加のインタープリターの作成をサポートしていますが( Py_NewInterpreter()を使用)、複数のインタープリターとPyGILState_*() APIの混合はサポートされていません。

スレッドについて注意すべきもう1つの重要な点は、C fork()呼び出しに直面したときのスレッドの動作です。 fork()を使用するほとんどのシステムでは、プロセスがフォークした後、フォークを発行したスレッドのみが存在します。 これは、他のスレッドによって保持されているロックが解放されないことも意味します。 Pythonは、フォークの前に内部で使用するロックを取得し、後で解放することで、 os.fork()のこれを解決します。 さらに、子のロックオブジェクトをリセットします。 Pythonを拡張または埋め込む場合、フォークの前に取得するか、フォークの後にリセットする必要がある追加の(Python以外の)ロックをPythonに通知する方法はありません。 同じことを実現するには、pthread_atfork()などのOS機能を使用する必要があります。 さらに、Pythonを拡張または埋め込む場合、 os.fork()を介さずにfork()を直接呼び出す(およびPythonに戻るか呼び出す)と、Pythonの内部ロックの1つによるデッドロックが発生する可能性があります。フォークの後で機能しなくなったスレッドによって保持されています。 PyOS_AfterFork()は必要なロックをリセットしようとしますが、常にリセットできるとは限りません。


高レベルAPI

これらは、C拡張コードを作成するとき、またはPythonインタープリターを埋め込むときに最も一般的に使用されるタイプと関数です。

type PyInterpreterState

このデータ構造は、多数の協調スレッドによって共有される状態を表します。 同じインタープリターに属するスレッドは、モジュール管理と他のいくつかの内部項目を共有します。 この構造にはパブリックメンバーはありません。

異なるインタープリターに属するスレッドは、使用可能なメモリ、開いているファイル記述子などのプロセス状態を除いて、最初は何も共有しません。 グローバルインタプリタロックは、どのインタプリタに属しているかに関係なく、すべてのスレッドで共有されます。

type PyThreadState
このデータ構造は、単一スレッドの状態を表します。 唯一のパブリックデータメンバーはPyInterpreterState * interpであり、これはこのスレッドのインタープリター状態を指します。
void PyEval_InitThreads()

グローバルインタプリタロックを初期化して取得します。 2番目のスレッドを作成する前、または PyEval_ReleaseLock()PyEval_ReleaseThread(tstate)などの他のスレッド操作を実行する前に、メインスレッドで呼び出す必要があります。 PyEval_SaveThread()または PyEval_RestoreThread()を呼び出す前に必要ありません。

これは、2回目に呼び出されたときは何もしません。 Py_Initialize()を呼び出す前に、この関数を呼び出しても安全です。

ノート

メインスレッドのみが存在する場合、GIL操作は必要ありません。 これは一般的な状況であり(ほとんどのPythonプログラムはスレッドを使用しません)、ロック操作によってインタープリターの速度が少し低下します。 したがって、ロックは最初は作成されません。 この状況は、ロックを取得したのと同じです。スレッドが1つしかない場合、すべてのオブジェクトアクセスは安全です。 したがって、この関数はグローバルインタプリタロックを初期化するときに、それも取得します。 Python _threadモジュールが新しいスレッドを作成する前に、ロックがあるか、ロックがまだ作成されていないことを認識して、 PyEval_InitThreads()を呼び出します。 この呼び出しが戻ると、ロックが作成され、呼び出し元のスレッドがロックを取得したことが保証されます。

現在どのスレッド(存在する場合)がグローバルインタープリターロックを持っているかが不明な場合、この関数を呼び出すことは安全ではありません

この機能は、コンパイル時にスレッドサポートが無効になっている場合は使用できません。

int PyEval_ThreadsInitialized()

PyEval_InitThreads()が呼び出された場合、ゼロ以外の値を返します。 この関数はGILを保持せずに呼び出すことができるため、シングルスレッドを実行しているときにロックAPIの呼び出しを回避するために使用できます。 この機能は、コンパイル時にスレッドサポートが無効になっている場合は使用できません。

バージョン2.4の新機能。

PyThreadState *PyEval_SaveThread()
グローバルインタプリタロックを解放し(作成されていて、スレッドサポートが有効になっている場合)、スレッドの状態を NULL にリセットして、前のスレッドの状態( NULL ではない)を返します。 ロックが作成されている場合は、現在のスレッドがロックを取得している必要があります。 (この機能は、コンパイル時にスレッドサポートが無効になっている場合でも使用できます。)
void PyEval_RestoreThread(PyThreadState *tstate)
グローバルインタプリタロックを取得し(作成されていて、スレッドサポートが有効になっている場合)、スレッドの状態を tstate に設定します。 NULL であってはなりません。 ロックが作成されている場合は、現在のスレッドがロックを取得していない必要があります。取得していないと、デッドロックが発生します。 (この機能は、コンパイル時にスレッドサポートが無効になっている場合でも使用できます。)
PyThreadState *PyThreadState_Get()
現在のスレッドの状態を返します。 グローバルインタプリタロックを保持する必要があります。 現在のスレッドの状態が NULL の場合、致命的なエラーが発生します(したがって、呼び出し元は NULL をチェックする必要がありません)。
PyThreadState *PyThreadState_Swap(PyThreadState *tstate)
現在のスレッド状態を、引数 tstate で指定されたスレッド状態と交換します。これは NULL の場合があります。 グローバルインタプリタロックを保持する必要があり、解放されません。
void PyEval_ReInitThreads()
この関数は PyOS_AfterFork()から呼び出され、新しく作成された子プロセスが、子プロセスで実行されていないスレッドを参照するロックを保持しないようにします。

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

PyGILState_STATE PyGILState_Ensure()

Pythonの現在の状態やグローバルインタープリターロックに関係なく、現在のスレッドがPython CAPIを呼び出す準備ができていることを確認します。 これは、各呼び出しが 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()への呼び出しのハンドルを保存する必要があります。

関数が戻ると、現在のスレッドはGILを保持し、任意のPythonコードを呼び出すことができます。 失敗は致命的なエラーです。

バージョン2.3の新機能。

void PyGILState_Release(PyGILState_STATE)

以前に取得したリソースを解放します。 この呼び出しの後、Pythonの状態は、対応する PyGILState_Ensure()呼び出しの前と同じになります(ただし、通常、この状態は呼び出し元に認識されないため、GILState APIが使用されます)。

PyGILState_Ensure()へのすべての呼び出しは、同じスレッドでの PyGILState_Release()への呼び出しと一致する必要があります。

バージョン2.3の新機能。

PyThreadState *PyGILState_GetThisThreadState()

このスレッドの現在のスレッド状態を取得します。 現在のスレッドでGILStateAPIが使用されていない場合、NULLを返す場合があります。 メインスレッドで自動スレッド状態の呼び出しが行われていなくても、メインスレッドには常にそのようなスレッド状態があることに注意してください。 これは主にヘルパー/診断機能です。

バージョン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

以下のすべての関数は、コンパイル時にスレッドサポートが有効になっている場合にのみ使用でき、グローバルインタープリターロックが作成されている場合にのみ呼び出す必要があります。

PyInterpreterState *PyInterpreterState_New()
新しいインタプリタ状態オブジェクトを作成します。 グローバルインタプリタロックを保持する必要はありませんが、この関数の呼び出しをシリアル化する必要がある場合は保持できます。
void PyInterpreterState_Clear(PyInterpreterState *interp)
インタプリタ状態オブジェクトのすべての情報をリセットします。 グローバルインタプリタロックを保持する必要があります。
void PyInterpreterState_Delete(PyInterpreterState *interp)
インタプリタ状態オブジェクトを破棄します。 グローバルインタプリタロックを保持する必要はありません。 インタプリタの状態は、 PyInterpreterState_Clear()への以前の呼び出しでリセットされている必要があります。
PyThreadState *PyThreadState_New(PyInterpreterState *interp)
指定されたインタプリタオブジェクトに属する新しいスレッド状態オブジェクトを作成します。 グローバルインタプリタロックを保持する必要はありませんが、この関数の呼び出しをシリアル化する必要がある場合は保持できます。
void PyThreadState_Clear(PyThreadState *tstate)
スレッド状態オブジェクトのすべての情報をリセットします。 グローバルインタプリタロックを保持する必要があります。
void PyThreadState_Delete(PyThreadState *tstate)
スレッド状態オブジェクトを破棄します。 グローバルインタプリタロックを保持する必要はありません。 スレッドの状態は、 PyThreadState_Clear()への前回の呼び出しでリセットされている必要があります。
PyObject *PyThreadState_GetDict()

拡張機能がスレッド固有の状態情報を格納できる辞書を返します。 各拡張機能は、ディクショナリに状態を格納するために使用する一意のキーを使用する必要があります。 現在のスレッド状態が利用できない場合は、この関数を呼び出してもかまいません。 この関数が NULL を返す場合、例外は発生しておらず、呼び出し元は現在のスレッド状態が利用できないと想定する必要があります。

バージョン2.3で変更:以前は、これは現在のスレッドがアクティブな場合にのみ呼び出すことができ、 NULL は例外が発生したことを意味していました。

int PyThreadState_SetAsyncExc(long id, PyObject *exc)

スレッドで非同期的に例外を発生させます。 id 引数は、ターゲットスレッドのスレッドIDです。 exc は、発生する例外オブジェクトです。 この関数は、 exc への参照を盗みません。 素朴な誤用を防ぐために、これを呼び出すために独自のC拡張機能を作成する必要があります。 GILを保持したまま呼び出す必要があります。 変更されたスレッド状態の数を返します。 これは通常1ですが、スレッドIDが見つからない場合は0になります。 excNULLの場合、スレッドの保留中の例外(存在する場合)はクリアされます。 これは例外を引き起こしません。

バージョン2.3の新機能。

void PyEval_AcquireThread(PyThreadState *tstate)

グローバルインタプリタロックを取得し、現在のスレッド状態を tstate に設定します。これは NULL であってはなりません。 ロックは以前に作成されている必要があります。 このスレッドがすでにロックを持っている場合、デッドロックが発生します。

PyEval_RestoreThread()は、常に使用可能な高レベルの関数です(スレッドのサポートが有効になっていない場合や、スレッドが初期化されていない場合でも)。

void PyEval_ReleaseThread(PyThreadState *tstate)

現在のスレッド状態を NULL にリセットし、グローバルインタープリターロックを解放します。 ロックは以前に作成されている必要があり、現在のスレッドによって保持されている必要があります。 tstate 引数は、 NULL であってはならず、現在のスレッド状態を表していることを確認するためにのみ使用されます。そうでない場合は、致命的なエラーが報告されます。

PyEval_SaveThread()は、常に使用可能な高レベルの関数です(スレッドのサポートが有効になっていない場合や、スレッドが初期化されていない場合でも)。

void PyEval_AcquireLock()

グローバルインタプリタロックを取得します。 ロックは以前に作成されている必要があります。 このスレッドがすでにロックを持っている場合、デッドロックが発生します。

警告

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

void PyEval_ReleaseLock()

グローバルインタプリタロックを解除します。 ロックは以前に作成されている必要があります。

警告

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


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

ほとんどの用途では、単一のPythonインタープリターのみを埋め込みますが、同じプロセスで、場合によっては同じスレッドでさえ、複数の独立したインタープリターを作成する必要がある場合があります。 サブインタープリターを使用すると、それを行うことができます。 PyThreadState_Swap()関数を使用して、サブインタープリターを切り替えることができます。 次の関数を使用して、それらを作成および破棄できます。

PyThreadState *Py_NewInterpreter()

新しいサブインタープリターを作成します。 これは、Pythonコードを実行するための(ほぼ)完全に独立した環境です。 特に、新しいインタプリタには、基本モジュールbuiltins__ main __sys を含む、インポートされたすべてのモジュールの個別の独立したバージョンがあります。 ロードされたモジュールのテーブル(sys.modules)とモジュール検索パス(sys.path)も分離されています。 新しい環境にはsys.argv変数がありません。 新しい標準I / Oストリームファイルオブジェクトsys.stdinsys.stdout、およびsys.stderrがあります(ただし、これらは同じ基になるファイル記述子を参照します)。

戻り値は、新しいサブインタープリターで作成された最初のスレッド状態を指します。 このスレッド状態は、現在のスレッド状態で作成されます。 実際のスレッドは作成されないことに注意してください。 以下のスレッド状態の説明を参照してください。 新しいインタプリタの作成に失敗した場合、 NULL が返されます。 例外状態は現在のスレッド状態に格納され、現在のスレッド状態がない可能性があるため、例外は設定されません。 (他のすべてのPython / C API関数と同様に、グローバルインタープリターロックはこの関数を呼び出す前に保持する必要があり、戻ったときに保持されます。ただし、他のほとんどのPython / C API関数とは異なり、現在のスレッド状態がオンである必要はありません。エントリ。)

拡張モジュールは、次のように(サブ)インタープリター間で共有されます。特定の拡張が最初にインポートされると、通常どおり初期化され、そのモジュールの辞書の(浅い)コピーが削除されます。 同じ拡張機能が別の(サブ)インタープリターによってインポートされると、新しいモジュールが初期化され、このコピーの内容が入力されます。 拡張機能のinit関数は呼び出されません。 これは、 Py_Finalize()および Py_Initialize()を呼び出してインタープリターが完全に再初期化された後に拡張機能がインポートされた場合とは異なることに注意してください。 その場合、拡張機能のinitmodule関数に再度呼び出されます。

void Py_EndInterpreter(PyThreadState *tstate)
指定されたスレッド状態で表される(サブ)インタープリターを破棄します。 指定されたスレッド状態は、現在のスレッド状態である必要があります。 以下のスレッド状態の説明を参照してください。 呼び出しが戻ると、現在のスレッドの状態は NULL です。 このインタプリタに関連付けられているすべてのスレッド状態が破棄されます。 (グローバルインタープリターロックは、この関数を呼び出す前に保持する必要があり、戻ったときにも保持されます。) Py_Finalize()は、その時点で明示的に破棄されていないすべてのサブインタープリターを破棄します。

バグと警告

サブインタープリター(およびメインインタープリター)は同じプロセスの一部であるため、それらの間の分離は完全ではありません。たとえば、 os.close()のような低レベルのファイル操作を使用できます(偶然または悪意を持って)お互いの開いているファイルに影響を与えます。 拡張機能が(サブ)インタープリター間で共有される方法のため、一部の拡張機能は正しく機能しない場合があります。 これは、拡張機能が(静的)グローバル変数を使用する場合、または拡張機能が初期化後にモジュールのディクショナリを操作する場合に特に発生します。 あるサブインタープリターで作成されたオブジェクトを別のサブインタープリターの名前空間に挿入することができます。 これは、サブインタープリター間でユーザー定義の関数、メソッド、インスタンス、またはクラスを共有しないように細心の注意を払って行う必要があります。そのようなオブジェクトによって実行されるインポート操作は、ロードされたモジュールの間違った(サブ)インタープリターのディクショナリに影響を与える可能性があるためです。

また、この機能をPyGILState_*() APIと組み合わせるのは微妙であることに注意してください。これらのAPIは、Pythonスレッドの状態とOSレベルのスレッドの間の全単射を想定しているためです。 一致する PyGILState_Ensure()呼び出しと PyGILState_Release()呼び出しのペア間でサブインタープリターを切り替えないことを強くお勧めします。 さらに、これらのAPIを使用してPythonで作成されていないスレッドからPythonコードを呼び出すことができる拡張機能( ctypes など)は、サブインタープリターを使用すると壊れてしまう可能性があります。


非同期通知

メインのインタプリタスレッドに非同期通知を行うメカニズムが提供されています。 これらの通知は、関数ポインタとvoidポインタ引数の形式を取ります。

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

メインのインタプリタスレッドから呼び出される関数をスケジュールします。 成功すると、0が返され、 func がメインスレッドで呼び出されるためにキューに入れられます。 失敗すると、例外を設定せずに-1が返されます。

正常にキューに入れられると、 func は、引数 arg を使用してメインインタープリタースレッドから最終的に呼び出されます。 通常実行されているPythonコードに関しては非同期で呼び出されますが、次の両方の条件が満たされています。

func は、成功した場合は0を返し、失敗した場合は例外セットを使用して-1を返す必要があります。 func は、別の非同期通知を再帰的に実行するために中断されることはありませんが、グローバルインタープリターロックが解放された場合でも、スレッドを切り替えるために中断される可能性があります。

この関数は、実行するために現在のスレッド状態を必要とせず、グローバルインタープリターロックも必要ありません。

警告

これは低レベルの関数であり、非常に特殊な場合にのみ役立ちます。 func ができるだけ早く呼び出されるという保証はありません。 メインスレッドがシステムコールの実行でビジー状態の場合、システムコールが戻る前に func は呼び出されません。 この関数は通常、任意のCスレッドからPythonコードを呼び出すのに適切ではありません。 代わりに、 PyGILState API を使用してください。

バージョン2.7の新機能。


プロファイリングとトレース

Pythonインタープリターは、プロファイリングおよび実行トレース機能をアタッチするための低レベルのサポートを提供します。 これらは、プロファイリング、デバッグ、およびカバレッジ分析ツールに使用されます。

Python 2.2以降、この機能の実装が大幅に改訂され、Cのインターフェイスが追加されました。 このCインターフェースにより、プロファイリングまたはトレースコードは、Pythonレベルの呼び出し可能オブジェクトを介した呼び出しのオーバーヘッドを回避し、代わりに直接C関数呼び出しを行うことができます。 施設の本質的な属性は変更されていません。 このインターフェースでは、トレース関数をスレッドごとにインストールできます。トレース関数に報告される基本的なイベントは、以前のバージョンのPythonレベルのトレース関数に報告されたものと同じです。

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

PyEval_SetProfile()および PyEval_SetTrace()を使用して登録されたトレース関数のタイプ。 最初のパラメータは、 obj として登録関数に渡されるオブジェクトです。 frame はイベントが関係するフレームオブジェクトであり、 what は定数の1つです[ X189X] 、PyTrace_EXCEPTIONPyTrace_LINEPyTrace_RETURNPyTrace_C_CALLPyTrace_C_EXCEPTION、またはPyTrace_C_RETURN、および arg は、 what の値によって異なります。

what の値

arg の意味

PyTrace_CALL

常に Py_None

PyTrace_EXCEPTION

sys.exc_info()によって返される例外情報。

PyTrace_LINE

常に Py_None

PyTrace_RETURN

呼び出し元に返される値、または例外が原因の場合は NULL

PyTrace_C_CALL

呼び出されている関数オブジェクト。

PyTrace_C_EXCEPTION

呼び出されている関数オブジェクト。

PyTrace_C_RETURN

呼び出されている関数オブジェクト。

int PyTrace_CALL
関数またはメソッドへの新しい呼び出し、またはジェネレーターへの新しいエントリが報告されているときの、 Py_tracefunc 関数に対する what パラメーターの値。 対応するフレームのPythonバイトコードへの制御転送がないため、ジェネレーター関数のイテレーターの作成は報告されないことに注意してください。
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 に異なる値を使用すると、それを格納するための便利でスレッドセーフな場所が提供されます。 プロファイル関数は、PyTrace_LINEPyTrace_EXCEPTIONを除くすべての監視対象イベントに対して呼び出されます。
void PyEval_SetTrace(Py_tracefunc func, PyObject *obj)
トレース機能を func に設定してください。 これは PyEval_SetProfile()に似ていますが、トレース関数が行番号イベントを受信し、呼び出されているC関数オブジェクトに関連するイベントを受信しない点が異なります。 PyEval_SetTrace()を使用して登録されたトレース関数は、 what パラメーターの値としてPyTrace_C_CALLPyTrace_C_EXCEPTION、またはPyTrace_C_RETURNを受け取りません。 。
PyObject *PyEval_GetCallStats(PyObject *self)

関数呼び出しカウントのタプルを返します。 タプル内の位置には次の定数が定義されています。

名前

価値

PCALL_ALL

0

PCALL_FUNCTION

1

PCALL_FAST_FUNCTION

2

PCALL_FASTER_FUNCTION

3

PCALL_METHOD

4

PCALL_BOUND_METHOD

5

PCALL_CFUNCTION

6

PCALL_TYPE

7

PCALL_GENERATOR

8

PCALL_OTHER

9

PCALL_POP

10

PCALL_FAST_FUNCTIONは、引数タプルを作成する必要がないことを意味します。 PCALL_FASTER_FUNCTIONは、高速パスフレームセットアップコードが使用されることを意味します。

引数タプルを変更して関数を直接呼び出すことで呼び出しを最適化できるメソッド呼び出しがある場合、2回記録されます。

この関数は、PythonがCALL_PROFILEを定義してコンパイルされている場合にのみ存在します。


高度なデバッガーのサポート

これらの関数は、高度なデバッグツールでのみ使用することを目的としています。

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)

同じ PyInterpreterState オブジェクトに属するすべてのそのようなオブジェクトのリストから、 tstate の次のスレッド状態オブジェクトを返します。

バージョン2.2の新機能。