Pythonで一番「謎」な一行 ―― if __name__ == "__main__" の正体
Pythonのコードをあれこれ眺めていると、ファイルの末尾でほぼ必ずと言っていいほどこの一行に出くわします。
if __name__ == "__main__":
main()
一見すると、おまじないのように見えるかもしれません。でも実際に何をしているのかを知れば、これがかなり実用的な仕組みだと分かってきます。そもそもこの書き方が存在するのは、Pythonが「スクリプト」と「ライブラリ」を明確に区別していないからなんです。
前提: ファイルには2つの使い方がある
Pythonの .py ファイルは、どれも2通りの使い方ができます。
- スクリプトとして —
python3 file.pyで直接実行する。 - モジュールとして — 別のファイルから
import fileで読み込む。
Pythonは「このファイルはどっちです」と宣言させるような言語ではありません。1つのファイルが両方の役割をこなすことも普通にあります。
math_helpers.py というファイルを例に考えてみましょう。
# math_helpers.py
def mean(values):
return sum(values) / len(values)
def median(values):
s = sorted(values)
mid = len(s) // 2
if len(s) % 2 == 0:
return (s[mid - 1] + s[mid]) / 2
return s[mid]
# Quick smoke test while developing
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("mean:", mean(numbers))
print("median:", median(numbers))
このファイルを直接実行するぶんにはテスト出力が表示されて便利です。でも他のファイルが import math_helpers した瞬間、その print はimport のタイミングで動いてしまうのが問題です。モジュールを使う人全員に、あなたの動作確認用の出力が丸見えになってしまいます。これはまずいですよね。
__name__ とは何か
Python のモジュールには必ず __name__ という組み込み変数が用意されていて、Python が自動で値をセットしてくれます。
- import されたとき、
__name__にはそのモジュールの import 名が入ります。上の例なら"math_helpers"ですね。 - ファイルを直接実行したときは、Python が
__name__に特別な文字列"__main__"を入れます。
つまりこの値を見れば、今どちらのモードで動いているかが判別できるわけです。スクリプトとしてだけ動かしたいコードは、次のようにチェックで囲んでやります。
# math_helpers.py
def mean(values):
return sum(values) / len(values)
def median(values):
s = sorted(values)
mid = len(s) // 2
if len(s) % 2 == 0:
return (s[mid - 1] + s[mid]) / 2
return s[mid]
if __name__ == "__main__":
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("mean:", mean(numbers))
print("median:", median(numbers))
こうしておけば、python3 math_helpers.py と実行したときだけテスト出力が表示されます。別のファイルから import math_helpers した場合は、このブロック自体がスキップされるので、関数だけが使える状態になり、余計な処理は一切走りません。
お決まりのパターン:main() 関数とセットで使う
実際のスクリプトでは、main() という関数を用意して、ガード側はできるだけシンプルに保つのが定番です。
# process_orders.py
import sys
def load_orders(path):
with open(path) as f:
return [line.strip() for line in f if line.strip()]
def process(orders):
for order in orders:
print(f"Processing {order}")
def main():
if len(sys.argv) < 2:
print("Usage: python3 process_orders.py <file>")
sys.exit(1)
orders = load_orders(sys.argv[1])
process(orders)
if __name__ == "__main__":
main()
if ガード直下にロジックを書かずに、わざわざ main() 関数を用意する意味は何でしょうか?
- テストしやすさ。 モジュールとして import して、
main()やヘルパー関数をテストから呼び出せます。 - ローカル変数になる。
main()の中で定義した変数はすべてローカル変数になり、モジュールレベルの名前にはなりません。これで名前の衝突を防げますし、モジュールの公開インターフェースもすっきりします。 - 読みやすさ。 ガードブロックがたった2行になるので、ごちゃごちゃしたロジックの塊ではなく、「スクリプトのエントリーポイントはここ」とひと目で分かります。
動きをサクッと確認してみる
実際の挙動はこんな感じで確認できます。
上記のコードをそのまま Python で実行すると、__name__ is: __main__ と表示され、続けて「being run as a script.」と出力されます。もし別のファイルからこのファイルを import した場合は、もう一方の分岐が実行されます。
if __name__ == "__main__" を書かなくていいケース
実際のところ、このガードを書かずに済ませている Python ファイルも山ほどあります。import されることを想定していない短いスクリプトなら、わざわざ書く必要はありません。
# one_off_rename.py
import os
for name in os.listdir("."):
if name.endswith(".txt"):
os.rename(name, name.lower())
それで十分です。ライブラリを作っているわけでも、誰かに import されるわけでもないですからね。ただ、ファイルに再利用したいロジックが登場した瞬間――そしてその横に実行用のコードも残しておきたくなった瞬間――このガードの出番になります。
インストール済みパッケージのエントリーポイント
自作コードを本格的にパッケージとして公開するようになると、もう少しフォーマルな仕組みが使えます。パッケージのメタデータに書く entry_points で、コマンドと関数を紐づける方法です。利用者はパッケージをインストールするだけで、その関数を直接呼び出すシェルコマンドが使えるようになります。とはいえ、自分のマシンのフォルダから普通にスクリプトを動かすぶんには、__main__ ガードが定番の道具です。
この章のまとめ
ここまでで、次のツールが手に入りました。
- ロジックに名前を付けるための関数
- 柔軟な呼び出しを可能にする
*args/**kwargs - 使い捨て関数としてのラムダ
- 関数をラップしたりドキュメント化したりするデコレータと型ヒント
- コードを複数ファイル・複数プロジェクトに分けるためのモジュール、pip、仮想環境
- スクリプトとモジュールを両立させる
__main__ガード
次はクラス
ここまでは、関数と素のデータ(辞書、リスト、タプル)を組み合わせて使ってきましたね。次の章ではクラスを取り上げます。Python でデータと振る舞いをひとまとめにするための仕組みで、self や __init__、継承、dataclass といったトピックが登場するのもこの章です。
よくある質問
if __name__ == '__main__' は何をしているの?
if __name__ == '__main__' は何をしているの?そのファイルが直接実行されたときだけ、下のブロックを走らせるための書き方です。モジュールとして import されたときには実行されません。つまり、同じ .py ファイルを「スクリプトとして実行」と「関数やクラスをインポートして再利用」の両方で使えるようになり、しかも import したときに余計なスクリプト処理が走らないようにできるわけです。
Python に main 関数は必要?
必須ではありません。Python のファイルは上から順に勝手に実行されるので、C や Java のような main() がなくても動きます。ただし、そのファイルを他のコードからも import したくなった瞬間に if __name__ == '__main__' ガードが重要になってきます。あわせて、スクリプト本体の処理を main() 関数にまとめておくのが定番の書き方です。
__name__ と __main__ って何が違うの?
__name__ と __main__ って何が違うの?__name__ は Python がすべてのモジュールに自動でセットする特殊変数です。ファイルが import された場合は、__name__ にモジュール名(たとえば 'util')が入ります。一方、ファイルを直接実行した場合は、Python が __name__ に '__main__' という文字列を入れます。if 文ではこの 2 つを比べているだけ、というわけです。