runpy --- Python モジュールの位置特定と実行

ソースコード: Lib/runpy.py


runpy モジュールは、Python モジュールをあらかじめインポートせずに見つけて実行するために使います。 主な用途はコマンドラインオプション -m の実装です。 このオプションを使うと、ファイルシステムではなく Python のモジュール名前空間からスクリプトを探せます。

これはサンドボックスモジュール ではない ことに注意してください。すべてのコードは現在のプロセスで実行され、あらゆる副作用 (たとえば他のモジュールのキャッシュされたインポート等) は関数から戻った後にそのまま残ります。

さらに、実行したコードで定義された関数やクラスが runpy の関数から戻った後も正しく動作する保証はありません。 この制約が用途に合わない場合は、このモジュールより importlib の方が適しているでしょう。

runpy モジュールは二つの関数を提供します。

runpy.run_module(mod_name, init_globals=None, run_name=None, alter_sys=False)

指定したモジュールのコードを実行し、実行後のモジュールのグローバル変数の辞書を返します。 まず標準のインポート機構 (詳細は PEP 302 を参照) でモジュールのコードを探し、新しいモジュール名前空間で実行します。

mod_name 引数には絶対モジュール名を指定します。 モジュール名が通常のモジュールではなくパッケージを指す場合は、そのパッケージをインポートしてから、パッケージ内の __main__ サブモジュールを実行し、実行後のモジュールのグローバル変数の辞書を返します。

省略可能な辞書引数 init_globals を使うと、コードの実行前にモジュールのグローバル変数の辞書に値を設定できます。 init_globals 自体は変更されません。 以下の特殊なグローバル変数が init_globals に定義されている場合、その定義は run_module() によって上書きされます。

モジュールのコードを実行する前に、特殊なグローバル変数 __name__、__spec__、__file__、__loader__、__package__ がグローバル変数の辞書に設定されます。 (これは最低限の変数の組であり、インタープリタの実装の詳細として他の変数が暗黙に設定される場合もあります。)

__name__ は、 run_name が None でない場合は run_name に設定されます。 run_name が None である場合、 mod_name がパッケージであれば mod_name + '.__main__' に、それ以外では mod_name に設定されます。

__spec__ には 実際に インポートするモジュールに適した値を設定します (つまり、__spec__.name は常に mod_name または mod_name + '.__main__' であり、run_name になることはありません)。

__file__、__loader__、__package__ はモジュール仕様に基づき 通常どおり設定されます。

引数 alter_sys が与えられて True に評価されるならば、 sys.argv[0] は __file__ の値で更新され sys.modules[__name__] は実行されるモジュールの一時的モジュールオブジェクトで更新されます。 sys.argv[0] と sys.modules[__name__] はどちらも関数が処理を戻す前にもとの値に復旧します。

この sys の操作はスレッドセーフではありません。 他のスレッドからは、初期化途中のモジュールや変更された引数リストが見える場合があります。 スレッドを使うコードからこの関数を呼び出す場合は、sys モジュールを変更しないことをお勧めします。

参考

コマンドラインから、 -m オプションを与えることで同じ機能を実現出来ます。

バージョン 3.1 で変更: __main__ サブモジュールを探してパッケージを実行する機能が追加されました。

バージョン 3.2 で変更: __cached__ グローバル変数が追加されました (PEP 3147 を参照)。

バージョン 3.4 で変更: PEP 451 で追加されたモジュール仕様の機能を活用するよう更新されました。 これにより、この方法で実行したモジュールの __cached__ を正しく設定できるようになり、実際のモジュール名を常に __spec__.name で取得できるようになりました。

バージョン 3.12 で変更: __cached__、__loader__、__package__ の設定は非推奨になりました。 代わりの方法については ModuleSpec を参照してください。

バージョン 3.15 で変更: グローバル変数 __cached__ は設定されなくなりました。

runpy.run_path(path_name, init_globals=None, run_name=None)

指定したファイルシステム上の場所にあるコードを実行し、実行後のモジュールのグローバル変数の辞書を返します。 CPython のコマンドラインに渡すスクリプト名と同様、file_path には Python ソースファイル、コンパイル済みのバイトコードファイル、または __main__ モジュールを含む有効な sys.path エントリー (例えば最上位に __main__.py がある zip ファイル) を指定できます。

単純なスクリプトの場合は、指定されたコードを新しいモジュール名前空間で実行するだけです。 有効な sys.path エントリー (通常は zip ファイルまたはディレクトリ) の場合は、まずそのエントリーを sys.path の先頭に追加します。 次に、更新されたパスを使って __main__ モジュールを探し、実行します。 指定した場所にそのモジュールがない場合、sys.path 上の別の場所にある既存の __main__ を実行しないようにする特別な保護はありません。

省略可能な辞書引数 init_globals を使うと、コードの実行前にモジュールのグローバル変数の辞書に値を設定できます。 init_globals 自体は変更されません。 以下の特殊なグローバル変数が init_globals に定義されている場合、その定義は run_path() によって上書きされます。

モジュールのコードを実行する前に、特殊なグローバル変数 __name__、__spec__、__file__、__loader__、__package__ がグローバル変数の辞書に設定されます。 (これは最低限の変数の組であり、インタープリタの実装の詳細として他の変数が暗黙に設定される場合もあります。)

__name__ は、オプション引数 run_name が None でない場合は run_name に設定されます。 run_name が None の場合は '<run_path>' に設定されます。

file_path がスクリプトファイル (ソースまたはコンパイル済みのバイトコード) を直接指す場合、__file__ は file_path に設定され、__spec__、__loader__、__package__ はすべて None に設定されます。

file_path が有効な sys.path エントリーを指す場合、__spec__ にはインポートする __main__ モジュールに適した値を設定します (つまり、__spec__.name は常に __main__ です)。 __file__、__loader__、__package__ はモジュール仕様に基づき 通常どおり設定されます。

sys モジュールにもいくつかの変更を加えます。 まず、上述のように sys.path を変更する場合があります。 sys.argv[0] を file_path の値に更新し、sys.modules[__name__] を実行対象のモジュールを表す一時的なモジュールオブジェクトに更新します。 sys 内の要素への変更はすべて、関数から戻る前に元に戻します。

run_module() とは異なり、この関数では sys への変更を省略できません。 sys.path エントリーの実行にはこれらの変更が必要なためです。 スレッドセーフに関する制約も同様にあるため、スレッドを使うコードでこの関数を使う場合は、インポートロックで実行を直列化するか、別のプロセスに実行を委ねてください。

参考

コマンドラインから インターフェイスオプション で同じ機能を使えます (python path/to/script)。

Added in version 3.2.

バージョン 3.4 で変更: PEP 451 で追加されたモジュール仕様の機能を活用するよう更新されました。 これにより、__main__ を直接実行するのではなく有効な sys.path エントリーからインポートする場合に、__cached__ を正しく設定できるようになりました。

バージョン 3.12 で変更: __cached__、__loader__、__package__ の設定は非推奨になりました。

バージョン 3.15 で変更: グローバル変数 __cached__ は設定されなくなりました。

参考

PEP 338 - モジュールをスクリプトとして実行する

PEP written and implemented by Nick Coghlan.

PEP 366 - main モジュールの明示的な相対インポート

PEP written and implemented by Nick Coghlan.

PEP 451 -- インポートシステムのための ModuleSpec 型

PEP written and implemented by Eric Snow

コマンドラインと環境 - CPython コマンドライン詳細

importlib.import_module() 関数