原文: Python if __name__ == __main__ Explained with Code Examples

Python インタープリターは、Python ファイルを読み込むとまずいくつか特別な変数を設定します。それからファイルに書かれたコードを実行します。

その変数の 1 つが __name__ です。

順を追ってこの記事とコードスニペットを読んでいけば、if __name__ == "__main__" の使い方とその重要性がわかるようになるでしょう。

Python モジュールの解説

Python ファイルは拡張子 .py が付くファイルで、モジュールとも呼ばれます。モジュールは、関数、クラス、そして変数を定義できます。

インタープリターがモジュールを実行する際、実行されるモジュールがメインプログラムの場合は、__name__ 変数が __main__ に設定されます。

しかしそのモジュールを他のモジュールからインポートしているコードの場合は、__name__ 変数はそのモジュールの名前に設定されます。

例を見てみましょう。file_one.py という名前の Python モジュールを作成し、その中にこのトップレベルコードを貼り付けてください。

# Python file_one モジュール

print("file_one の __name__ の設定内容: {}".format(__name__))
file_one.py

このファイルを実行すると、先ほど述べた内容が確認できます。このモジュールの変数 __name____main__ に設定されます。

file_one の __name__ の設定内容: __main__

(訳注: 実行時に SyntaxError: Non-ASCII character '\xe3' in file file_one.py on line 1, but no encoding declared というエラーが発生する場合は、Python 3.x 系で実行するか、ファイルの先頭に # -*- coding: utf-8 -*- という行を追加してください。)

ではもう 1 つ file_two.py という名前のファイルを追加して、中にこのコードを貼り付けてください。

# インポートする Python モジュール

print("file_two の __name__ の設定内容: {}".format(__name__))
file_two.py

そして file_two モジュールをインポートするために、file_one.py のコードを次のように変更してください。

# 実行する Python モジュール
import file_two

print("file_one の __name__ の設定内容: {}".format(__name__))
file_one.py

もう一度 file_one のコードを実行すると、file_one__name__ 変数は変わらず __main__ のままですが、file_two__name__ 変数はモジュール名、つまり file_two に設定されます。

実行結果は次のようになります。

file_two の __name__ の設定内容: file_two
file_one の __name__ の設定内容: __main__

しかし直接 file_two を実行した場合には、__name____main__ に設定されるのが確認できます。

file_two の __name__ の設定内容: __main__

実行するファイル / モジュールの __name__ 変数は常に __main__ となります。ですがその他のインポートされたモジュールの __name__ 変数は、モジュール名に設定されます。

Python ファイルの命名規則

__name____main__ は通常このような形で使われます。

if __name__ == "__main__":
    # ここに処理内容を記述

これがどのように機能するか、そしてこれらの変数をどうやって使うかを見ていきましょう。

file_onefile_two を次のように変更してください。

file_one:

# 実行する Python モジュール
import file_two

print("file_one の __name__ の設定内容: {}".format(__name__))

if __name__ == "__main__":
    print("file_one が直接実行されました")
else:
    print("file_one がインポートされて実行されました")
file_one.py

file_two:

# インポートする Python モジュール

print("file_two の __name__ の設定内容: {}".format(__name__))

if __name__ == "__main__":
    print("file_two が直接実行されました")
else:
    print("file_two がインポートされて実行されました")
file_two.py

先ほどと同様に file_one を実行すると、プログラムが 2 つのモジュールのどちらが __main__ かを認識して、if else 文に従ってコードを実行したことが確認できます。

実行結果は次のようになります。

file_two の __name__ の設定内容: file_two
file_two がインポートされて実行されました
file_one の __name__ の設定内容: __main__
file_one が直接実行されました

今度は file_two を実行してみると、__name__ 変数が __main__ に設定されることが確認できます。

file_two の __name__ の設定内容: __main__
file_two が直接実行されました

このようなモジュールがインポートまたは実行されると、関数がインポートされ、トップレベルコードが実行されます。

その処理の動作を確認するために、ファイルを次のように変更しましょう。

file_one:

# 実行する Python モジュール
import file_two

print("file_one の __name__ の設定内容: {}".format(__name__))

def function_one():
    print("function_one が実行されました")

def function_two():
    print("function_two が実行されました")

if __name__ == "__main__":
    print("file_one が直接実行されました")
else:
    print("file_one がインポートされて実行されました")
file_one.py

file_two:

# インポートする Python モジュール

print("file_two の __name__ の設定内容: {}".format(__name__))

def function_three():
    print("function_three が実行されました")

if __name__ == "__main__":
    print("file_two が直接実行されました")
else:
    print("file_two がインポートされて実行されました")
file_two.py

これで関数が読み込まれますが、実行はされません。

関数を実行するには、file_oneif __name__ == "__main__" の部分を次のように変更してください。

if __name__ == "__main__":
    print("file_one が直接実行されました")
    function_two()
else:
    print("file_one がインポートされて実行されました")

file_one を実行すると次のように表示されるはずです。

file_two の __name__ の設定内容: file_two
file_two がインポートされて実行されました
file_one の __name__ の設定内容: __main__
file_one が直接実行されました
function_two が実行されました

また、インポートしたファイルの関数を実行することもできます。file_oneif __name__ == "__main__" の部分を次のように変更しましょう。

if __name__ == "__main__":
    print("file_one が直接実行されました")
    function_two()
    file_two.function_three()
else:
    print("file_one がインポートされて実行されました")

実行結果は次のようになるでしょう。

file_two の __name__ の設定内容: file_two
file_two がインポートされて実行されました
file_one の __name__ の設定内容: __main__
file_one が直接実行されました
function_two が実行されました
function_three が実行されました

ここで、例えば file_two モジュールが大きくなってたくさんの関数があり (この例では 2 つですが)、その全部はインポートしたくない場合を考えます。file_two を次のように変更してください。

# インポートする Python モジュール

print("file_two の __name__ の設定内容: {}".format(__name__))

def function_three():
    print("function_three が実行されました")

def function_four():
    print("function_four が実行されました")

if __name__ == "__main__":
    print("file_two が直接実行されました")
else:
    print("file_two がインポートされて実行されました")
file_two.py

モジュールから特定の関数をインポートするには、file_one ファイルで from import ブロックを使います。

# 実行する Python モジュール
from file_two import function_three

print("file_one の __name__ の設定内容: {}".format(__name__))

def function_one():
    print("function_one が実行されました")

def function_two():
    print("function_two が実行されました")

if __name__ == "__main__":
    print("file_one が直接実行されました")
    function_two()
    function_three()
else:
    print("file_one がインポートされて実行されました")
file_one.py

まとめ

ファイルをメインプログラムとして実行できるようにしたい場合でも、他のモジュールにインポートされるようにしたい場合でも、__name__ 変数が便利に使える場面があります。if __name__ == "__main__" ブロックを使って、モジュールがインポートされた場合にコードの一部を実行可能にしたり、あるいは不可にしたりできます。

Python インタープリターがファイルを読み込むと、実行中モジュールの場合には __name__ 変数は __main__ に、インポートされた場合にはモジュール名に設定されます。ファイルを読み込むとすべてのトップレベルコードが実行されますが、関数やクラスは実行されません。(インポートされるだけです。)

Bra gjort! (スウェーデン語で「よくできました」という意味です!)

筆者の freeCodeCamp プロフィールMedium プロフィールからこのような記事をもっと読むことができます。その他の作品は GitHub ページをチェックしてください。