Pythonスクリプトでよく使う以下のイディオムですが、今回はこの意味の説明と、pythonコマンドで実行可能なスクリプトの作成方法について説明します。
if __name__ == '__main__': # 処理
Contents
変数__name__と"__main__"
変数__name__に格納されているもの
まず、__name__という特別な変数ですが、これには現在実行中のモジュールの完全修飾名が格納されます。ただし、いつでもモジュール名が格納されるわけではなく、実行時のトップレベル(いわゆるエントリーポイント)のモジュールの場合は"__main__"という文字列が格納されます。つまり、そのモジュールがスクリプトのエントリーポイントとして実行されたかどうかはこの__name__が__main__かどうかで判定することが可能、ということです。したがって、スクリプトとして実行された場合の挙動は冒頭のif文の後に記述すれば良いわけです。
ただし、__name__に格納される値については他にも例外があります。代表的なものとして、パッケージの__init__.pyが挙げられます。このモジュールの__name__にはパッケージ名が格納されます。ここまでの説明が飲み込めない方も多いと思いますが、次のサンプルを実行してみると理解が深まると思います。
理解を深めるためのサンプル
カレントディレクトリにsample.pyとpkg1パッケージが配置されているものとします。また、pkg1配下には__init__.pyとmod1.pyが配置されているものとします。
. ├── pkg1 │ ├── __init__.py │ └── mod1.py └── sample.py
それぞれ以下のコードを記述します。
sample.py
# sample.py from pkg1 import mod1 def func1(): print('sample.py : ' + __name__) mod1.func1() if __name__ == '__main__': func1()
pkg1/__init__.py
# __init__.py print('__init__.py : ' + __name__)
pkg1/mod1.py
# pkg1/mod1.py def func1(): print('pkg1/mod1.py : ' + __name__) if __name__ == '__main__': func1()
コードの解説です。カレントディレクトリのsample.pyを実行すると、パッケージとそのモジュールmod1.pyを読み込みます。それぞれのpythonファイルは__name__の値を表示するだけのプログラムです。また、パッケージ配下のmod1モジュールは実行可能となっています。
それではまず、カレントディレクトリのsample.pyを実行してみましょう。
$ python sample.py __init__.py : pkg1 sample.py : __main__ pkg1/mod1.py : pkg1.mod1
いかがでしょうか。まず、トップレベルのモジュールであるsample.pyの__name__の値は"__main__"であることが確認できます。また、モジュールのmod1の名前はモジュールの完全修飾名(パッケージ名を含んでいる)が格納されています。そして、__init__.pyの__name__にはパッケージ名が格納されています。
一方、mod1.pyを実行してみます。
$ python pkg1/mod1.py pkg1/mod1.py : __main__
先ほどモジュールの完全修飾名が格納されていましたが、こんどは"__main__"が格納されていることが確認できます。
-mオプション 実行可能パッケージ __main__.py
さて、if ...で実行可能なスクリプトを作成することができましたが、実はパッケージに対しても可能です。パッケージ配下に__main__.pyという名前のモジュールを作成し、poythonコマンド実行時に-mオプションを付与します。先ほどのpkg1パッケージに以下のように__main__.pyを作成してみましょう。
# pkg/__main__.py import pkg1.mod1 pkg1.mod1.func1()
-mオプションをつけて実行してみます。
$ python -m pkg1 __init__.py : pkg1 pkg1/mod1.py : pkg1.mod1
__main__.pyが実行されたことが確認できました。
実行可能な組込みモジュール例
モジュールとして実行可能なパッケージですが、標準ライブラリには便利なツールとして実行可能なパッケージがいくつか提供されています。例えば、json.toolなんかが有名ですね。これは引数で指定したjson文字列を読みやすくダンプしてくれます。実行例を見てみましょう。sample.jsonというファイルにjson文字列が格納されているものとします。-mオプションを指定して実行すると以下のように出力されます。
$ python -m json.tool sample.json { "key1": 100, "key2": [ 1, 2, 3, 4 ], "key3": { "key4": 100, "key5": 200 } }