🦄

Pythonスクリプトの定型文 if __name__ == '__main__': main() の意味

2020/10/26に公開

初投稿です。手始めに、Python のコードを調べている時に頻出する、 以下のコードの意味について書いてみました。

def main():
    ~
if __name__ == '__main__':
    main()

これを理解するには、

  1. import の挙動
  2. _name_
    について理解する必要があります。

1. import の挙動

まず、test1.py というファイル名のスクリプトを準備します。

test1.py
def main():
    print('test1の関数です。')
main()
$ python test1.py
test1の関数です。

次に、test1.py をインポートしている、test2.py を準備します。

test2.py
import test1
def main():
    print('test2の関数です。')
main()
$ python test2.py
test1の関数です。
test2の関数です。

test2.py には、test1.main()の記載がありません。
このことから、test1.py がインポートされた時にtest1.main()が実行されていることがわかります。


2. _name_

次に、_name_についてです。
まず、test3.py を準備します。

test3.py
print(__name__)
$ python test3.py
__main__

_name_には、 '_main_' が格納されています。
次に、test3.py をインポートする test4.py を準備します。

test4.py
import test3
print(test3.__name__)
print(__name__)
$ python test4.py
test3
test3
__main__

test3.py を実行した時には、test3.py の_name_には、 '_main_' が格納されていましたが、インポートすると test3 の_name_には 'test3' が格納されました。つまり、インポートした時に_name_はファイル名に置き換えられます。


本題

ファイル内の関数を実行せずインポートしたい時、いよいよ本題である以下の形式が活きてきます。

def main():
    ~
if __name__ == '__main__':
    main()

まずはtest5.pyを準備します。

test5.py
def main():
    print('test5の関数です。')

if __name__ == '__main__':
    main()
$ python test5.py
test5の関数です。

次に、test5.py をインポートした test6.py を準備します。

test6.py
import test5
def main():
    print('test6の関数です。')

if __name__ == '__main__':
    main()
$ python test6.py
test6の関数です。

test5.py, test6.py は、test1.py, test2.py にif文を加えたものです。
if文を加えることで、test5.main()が実行されなくなりました。
これは、test5 をインポートした時、test5 の_name_ が、 '_main_' \rightarrow 'test5' に置き換わったためです。
今回は関数名に main を使用しましたが、関数名として成り立つ文字列であれば他のものに変えても影響ありません。慣例として、main が使われているのでしょうか。


まとめ

if _name_ == '_main_': main() を記載することで、「インポートされた時に関数が実行されない」スクリプトになりました。モジュールとして扱いやすくなりましたね。
間違っている記述等ありましたら、コメント頂けますと幸いです。

Discussion