#動作概要
以下のように、xxxx (例:http.serverやpdb)でモジュールを指定して実行出来る。
python -m xxxx yyyy.py
上記のコマンドでは、module(モジュール)が直接呼び出されたとき、いずれか(ファイルもしくはディレクトリ)の処理が行われる。
- (ファイル)該当Pythonスクリプトが実行される。具体的には、
__name__
変数が__main__
となる時の処理が、実行される。 - (ディレクトリ)該当ディレクトリを指定した場合、配下にある
__main__.py
というファイルが、実行される。
これにより、(モジュールとして呼び出している)スクリプトxxxxから(最終的に解析を行う)スクリプトyyyyを呼び出す処理等が容易に出来る。
これは、PEP338で定義されておりPythonでは、runpyモジュールで実装されている。
#モジュール実行をサポートしているモジュール例
Python組み込みだと以下のモジュールが代表的なものである。
- http.server (Webサーバ)
- pdb (デバッガ)
- cProfile (プロファイラ)
- unittest (テストフレームワーク)
それ以外だと、以下がある。なお、pytestには、更に似たようなpluginsのロード機能がある (-pオプション)。
- pytest (テストフレームワーク)(上記unittestの機能拡張のようなもの)
- tensorboard(機械学習モニタリングツール)(python -m tensorboard.mainで使う)
#Pythonインタープリターでの変数設定
さて、Pythonインタープリターは、Pythonスクリプトを実行する時に該当スクリプトのグローバル変数、__name__
等を設定する。直接呼び出されたファイルでは、__name__
は__main__
と設定される。設定されているパラメータは、Pythonから組み込み関数globals()
を実行することにより確認できる。なお、グローバル変数を設定する関数はC言語だが_run_code
である。
#参考資料
##概要説明資料
- (Python)runpy — Locating and executing Python modules(モジュールオプションを受けて実行処理をする関数の説明)
-
pytestのプラグイン組み込み
- pluggy(pytestのプラグイン管理ライブラリ)
##ソースコード
Python 3.7のコードより
-
Py_Main
- pymain_parse_cmdline(コマンドラインのパース)
-
pymain_run_module(モジュールの実行)
- [def
_run_module_as_main
] (https://github.com/python/cpython/blob/3.7/Lib/runpy.py#L167) (runpyモジュール)-
def _run_code(code, run_globals, init_globals=None, mod_name=None, mod_spec=None, pkg_name=None, script_name=None)
(Pythonスクリプトのグローバル変数設定関数。4番目の引数で__name__
を__main__
と設定))
-
- [def
- Pythonに同梱されているモジュール例
-
http.server Lib/http/server.py
__main__
(http.serverモジュールの__main__
)- Lib/_compat_pickle.py(Python2のSimpleHTTPServerからPython3のhttp.serverへのマッピング)
-
pdb Lib/pdb.py
__main__
(pdbモジュールの__main__
)-
class Pdb(bdb.Bdb, cmd.Cmd)(do_xxxxが、pdbのコマンド処理に該当する)
- class Bdb(Pythonデバッガの基本モジュール)
-
class Pdb(bdb.Bdb, cmd.Cmd)(do_xxxxが、pdbのコマンド処理に該当する)
-
cProfile Lib/cProfile.py
-
cProfilerクラスの親"_lsprof.Profiler"(C言語で実装されている。)
- PyEval_SetProfile等のCPython内のプロファイル関数等により(時間等の)プロファイルを取得する。
-
cProfilerクラスの親"_lsprof.Profiler"(C言語で実装されている。)
-
unittest """Main entry point"""(ディレクトリを指定したUnittestの例
__main__.py
から処理が行われる。)-
main(unittestのメイン)
- _do_discovery(test*.pyというファイルの検索ルーチン)
-
main(unittestのメイン)
-
http.server Lib/http/server.py
その他のモジュール
-
pytest (pytestモジュールの
__main__
)-
_pytest.config.main
- def wrap_session(config, doit)(テストスクリプトを呼び出す箇所。実際のエラー出力もここで行う。)
- pytest-dev/pluggy(pytest用のプラグインをキックする仕組み)
-
その他
- (StackOverflow)What is the Python 3 equivalent of “python -m SimpleHTTPServer”
- SimpleHTTPServerがあったのは、Python2までである。Python3でも同じ引数は残っているが、http.serverにマップされるだけである。 定義箇所は、上記のhttp.serverのソースコードの項を参照のこと