Pythonのif __name__ == '__main__'の意味と使い方
Python初心者がサンプルコードを見たときに理解に苦しむのが、おまじないのように書かれているif __name__ == '__main__'。
アンダースコアに惑わされるが「__name__に格納されている値が'__main__'という文字列であれば、以降の処理を実行する」という単なるif文。
__name__と'__main__'の意味が分かれば理解できる。
なお、Pythonでは文字列リテラルをシングルクォート'でもダブルクォート"でも表せるので、if __name__ == "__main__"でも同じ意味。
__name__とは
モジュールをインポートするとその__name__属性にモジュールの名前が文字列として格納される。<モジュール名>.__name__で取得できる。
import math
import numpy as np
print(math.__name__)
# math
print(np.__name__)
# numpy
自作のモジュールでも同じ。例として以下のようなモジュールhello(hello.py)を作成する。モジュール内で__name__を出力する関数を定義している。
def func():
print('Hello!')
print('__name__ is', __name__)
このモジュールhelloをインポートして使うと以下のようになる。
import hello
print(hello.__name__)
# hello
hello.func()
# Hello!
# __name__ is hello
インポートされたモジュールの__name__にはモジュール名'hello'が格納されていることが分かる。
'__main__'とは
上述のように、別のファイルからインポートされると__name__にはモジュール名が格納される。
一方、ファイルをコマンドラインからスクリプトとして実行すると__name__には'__main__'という文字列が格納される。
例としてtest_moduleというモジュール(test_module.py)とそれをインポートして使うtest_main.pyを作成する。
def func():
print(' This is func() in test_module.py')
print(' __name__ is', __name__)
if __name__ == '__main__':
print("Start if __name__ == '__main__'")
print('call func()')
func()
import test_module
print('This is test_main.py')
print('test_module.__name__ is', test_module.__name__)
print('---')
print('call test_module.func()')
test_module.func()
test_main.pyをコマンドラインからpython(またはpython3)コマンドで実行すると以下のような結果となる。
python3 test_main.py
# This is test_main.py
# test_module.__name__ is test_module
# ---
# call test_module.func()
# This is func() in test_module.py
# __name__ is test_module
helloの例と同様に、インポートされたモジュールtest_moduleの__name__にはモジュール名'test_module'が格納されている。
一方、test_module.py自体をコマンドラインから実行すると以下のような結果となる。
python3 test_module.py
# Start if __name__ == '__main__'
# call func()
# This is func() in test_module.py
# __name__ is __main__
__name__には'__main__'という文字列が格納され、if __name__ == '__main__':以降の処理が実行されていることが分かる。
このように、他のファイルからインポートされた場合は__name__に'<モジュール名>'が格納され、コマンドラインからpython(またはpython3)コマンドで実行された場合は__name__に'__main__'という文字列が格納される。
なお、pythonコマンドに-mオプションをつけてモジュールとして実行する場合やインタラクティブモードでも__name__には'__main__'という文字列が格納される。
python3 -m test_module
# Start if __name__ == '__main__'
# call func()
# This is func() in test_module.py
# __name__ is __main__
if __name__ == '__main__'の意味
まとめると、__name__に格納される値は以下の通り。
- 他のファイルからインポートされたとき
__name__は'<モジュール名>'
- そのファイル自体が
python(またはpython3)コマンドでスクリプトとして実行されたとき__name__は'__main__'
したがって、if __name__ == '__main__'は「このファイルがコマンドラインからスクリプトとして実行された場合にのみ以降の処理を実行する」という意味となる。他のファイルからインポートされたときは処理は実行されない。
if __name__ == '__main__'の使い方、使いどころ
if __name__ == '__main__'を使うと、モジュールのテストコードを記述したり、モジュールをコマンドとして利用できるようにしたりできる。
モジュールのテストコードを記述
モジュールの関数の出力結果を確認したいというような場合に、if __name__ == '__main__'以下にテストコードを書いておく。
例えば上述のhello.pyの場合。
def func():
print('Hello!')
print('__name__ is', __name__)
関数が定義されているだけなので、このファイルをコマンドラインから実行してもなにも起こらない。
python3 hello.py
if __name__ == '__main__'を追加する。
def func():
print('Hello!')
print('__name__ is', __name__)
if __name__ == '__main__':
func()
これをコマンドラインから実行すると、if __name__ == '__main__'以下のコードに従ってモジュール内の関数が実行される。
python3 hello_if_name.py
# Hello!
# __name__ is __main__
他のファイルからインポートされた場合はif __name__ == '__main__'以下のコードは実行されないので、余計な処理が発生することはない。
モジュールをコマンドとして利用
モジュールをコマンドとして利用したい場合にもif __name__ == '__main__'が使える。
以下のようなモジュールを作成する。
import sys
def add(a, b):
return a + b
if __name__ == '__main__':
print(add(int(sys.argv[1]), int(sys.argv[2])))
if __name__ == '__main__'以下ではsys.argvでコマンドライン引数を取得しモジュール内の関数に渡している。
sys.argvはコマンドライン引数のリストで最初の要素sys.argv[0]はスクリプト名となる。また、文字列として格納されるので数値として扱いたい場合はint(), float()などで変換する必要がある。
これによって、コマンドラインから引数をつけて実行した場合、モジュール内の関数が処理される。
python3 add_module.py 100 200
# 300
他のファイルからインポートして使うことももちろん可能。この場合はif __name__ == '__main__'以下のコードは実行されない。
import add_module
print(add_module.add(100, 200))
# 300
なお、モジュールをコマンドとして使いたい場合は、そのためのファイルを別途用意してもよい。
import sys
import add_module
print(add_module.add(int(sys.argv[1]), int(sys.argv[2])))
これを実行した結果は以下の通り。
python3 add_module_command.py 100 200
# 300
この場合、if __name__ == '__main__'は必要ない。
特にargparseモジュールなどを使ってコマンド化する場合は別のファイルにしたほうがスッキリする。
import argparse
import add_module
parser = argparse.ArgumentParser()
parser.add_argument('a', type=int)
parser.add_argument('b', type=int)
args = parser.parse_args()
print(add_module.add(args.a, args.b))
これを実行した結果は以下の通り。
python3 add_module_argparse.py 100 200
# 300
Pythonにおけるmain()関数
ついでにPythonにおけるmain()関数にも触れておく。
PythonではC言語のようにmain()関数から処理が実行されるというわけではなく、mainという名前の関数を定義したからといって自動的にその関数から処理が始まるわけではない。
以下の2つのコードはどちらも同じ実行結果となる。
main()関数を記述。
def main():
print('Hello!')
if __name__ == '__main__':
main()
処理を直接記述。
print('Hello!')
コマンドラインから実行したときの結果は同じ。
python3 hello_main.py
# Hello!
python3 hello_direct.py
# Hello!
特に大規模なプログラムの場合は慣例として起点となる関数をmain()という名前にしておくことが多いが、これはあくまでも分かりやすさのためで、仕様として特別な意味はないし、必須でもない。