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
}
}
