Pythonで書いたファイルは、直接実行する時と他のファイルからimportする時で挙動を切り替えられます。
この記事では、その鍵となるif __name__ == "__main__":
の意味と使い方を、初心者の方にも分かりやすく丁寧に解説します。
実行時だけ動かす処理の基本パターンを覚えると、サンプル実行やCLIの起動、テストのしやすさに直結します。
Pythonのif __name__ == “__main__”:とは
__name__の意味と値(mainとモジュール名)
__name__
は、Pythonが各モジュールごとに自動的に用意する特別な変数です。
ファイルが「プログラムの入り口」として実行される時は__name__
が"__main__"
になり、他のファイルからimport
された時は、そのモジュール名になります。
これを利用すると、「直接実行された時だけ動かしたい処理」を判定できます。
実演コードと出力
まずは__name__
の値を観察してみます。
# ファイル名: show_name.py
# __name__ の中身を表示するだけのスクリプト
print(f"__name__ の値は: {__name__}")
# 実行結果(直接実行)
$ python show_name.py
__name__ の値は: __main__
次に、別ファイルからimport
してみます。
# ファイル名: run_show_name.py
# show_name を import して、自分側と相手側の __name__ を比較
import show_name # ここで show_name.py のトップレベルが評価される
print(f"import側の __name__ は: {__name__}")
print(f"importした show_name.__name__ は: {show_name.__name__}")
# 実行結果(run_show_name.py を実行)
$ python run_show_name.py
__name__ の値は: show_name
import側の __name__ は: __main__
importした show_name.__name__ は: show_name
注意: importされたモジュールのトップレベル(ファイル直下)のコードは、import時に実行されます。
これが「副作用」と呼ばれる挙動で、後述のガードで制御します。
スクリプトとモジュールの違い
- スクリプトとは、そのファイル自体をエントリーポイントとして
python ファイル名.py
で実行する使い方です。 - モジュールとは、他のファイルから
import
して利用されるコードの単位です。ファイル名(拡張子を除く)がそのままモジュール名になります。
以下は、__name__
の値がどう変わるかの早見表です。
実行方法 | 説明 | そのファイル内の __name__ の値 |
---|---|---|
python foo.py | 直接実行(スクリプト) | "__main__" |
他ファイルから import foo | モジュールとして読み込み | "foo" |
python -m pkg.mod | モジュールとして起動 | "__main__" |
対話環境(REPL/Jupyter) | 対話の実行主体 | "__main__" |
なぜこの判定が必要か
「importしただけで余計な処理が走る」のを避け、再利用性と安全性を高めるためです。
例えばデータベース初期化やファイル書き込み、ネットワークアクセスのような「副作用」は、import
時に勝手に起きるべきではありません。
if __name__ == "__main__":
で囲むことで、スクリプト起動時だけ本処理を実行し、モジュールとして利用される時は関数やクラスの定義だけを提供できます。
Pythonスクリプト実行時だけ処理を動かす基本
基本の書き方(if __name__ == “__main__”:)
最小構成は次のようになります。
関数やクラスの定義はファイルの上側に記述し、if __name__ == "__main__":
以下にスクリプトとして起動された時だけの処理を書きます。
# ファイル名: hello.py
# スクリプトとして直接実行された時だけ greet("world") を実行する例
def greet(name: str) -> None:
"""名前に挨拶する簡単な関数"""
print(f"Hello, {name}!")
if __name__ == "__main__":
# ここは「このファイルを直接実行した時」だけ通る
greet("world")
# 実行結果(直接実行)
$ python hello.py
Hello, world!
# 実行結果(import時は何も表示されない)
$ python -c "import hello"
# (出力なし)
main関数を作るエントリーポイント
処理の入り口をmain()
関数にまとめると、コードの見通しが良くなります。
終了コードを返す場合はsys.exit(main())
の形が定番です。
# ファイル名: app.py
# エントリーポイントを main() にまとめた構成
def main() -> int:
"""アプリのエントリーポイント"""
print("アプリを開始します")
# ...ここにメイン処理を書く...
return 0 # 0は正常終了
if __name__ == "__main__":
# main() の戻り値をプロセスの終了コードとして返す
import sys
sys.exit(main())
# 実行結果(直接実行)
$ python app.py
アプリを開始します
# 実行結果(import時は何も表示されない)
$ python -c "import app"
# (出力なし)
実行フローのイメージ
Pythonがファイルを読み込むと、まずトップレベルの定義が順に評価され、続いてif __name__ == "__main__":
の判定に進みます。
流れは次の通りです。
- インタプリタがファイルを読み込むと同時に、
__name__
を設定する。 - 関数やクラス定義が評価され、メモリに登録される。
- ファイル直下の式や
print
などがあれば即時に実行される。 if __name__ == "__main__":
の条件がTrue
なら、そのブロック内の処理を実行する。- 他ファイルから
import
された場合は、4がFalse
になり、ブロックは実行されない。
「トップレベルでは定義だけ、実行はガードの中に」が安全な書き方です。
Pythonでimport時に動かさないメリット
再利用性とテストのしやすさ
import時に余計な処理が動かないという性質は、ユニットテストや再利用の観点で極めて重要です。
テスト側から関数やクラスを読み込みたいだけなのに、いきなりネットワーク通信や重い計算が走ると、テストが不安定になったり遅くなります。
ガードを使えば、純粋にAPIだけを提供できます。
サンプル実行と本処理を分ける
同じファイルに、サンプル実行用のデモと実際に提供する関数を共存させたい時にも便利です。
# ファイル名: worker.py
# ライブラリとして再利用できる関数と、スクリプト実行時のサンプル出力を同居
def square(n: int) -> int:
"""nの二乗を返す"""
return n * n
if __name__ == "__main__":
# ここはサンプルデモ。import時には実行されない。
print("square の簡単な動作確認")
for i in range(3):
print(f"{i}^2 = {square(i)}")
# 実行結果(直接実行)
$ python worker.py
square の簡単な動作確認
0^2 = 0
1^2 = 1
2^2 = 4
importでの副作用を防ぐ
悪い例として、トップレベルで初期化や書き込みを行うと、import
しただけで処理が発火します。
# ファイル名: bad_module.py
# 悪い例: import しただけで初期化が走る
def init_db() -> None:
print("DBを初期化しました")
# ここはファイル直下(トップレベル)。import時にも実行されてしまう。
init_db()
# ファイル名: use_bad_module.py
import bad_module
print("アプリを続行します")
$ python use_bad_module.py
DBを初期化しました
アプリを続行します
本来は「DBの初期化」は、明示的にユーザが起動した時だけ行うべき処理です。
次のようにガードで囲むと、安全にできます。
# ファイル名: good_module.py
# 良い例: 直接実行された時だけ初期化する
def init_db() -> None:
print("DBを初期化しました")
if __name__ == "__main__":
# 直接実行した時だけ DB 初期化を走らせる
init_db()
# ファイル名: use_good_module.py
import good_module
print("アプリを続行します")
$ python use_good_module.py
アプリを続行します
ガードの外に副作用のある処理を置かないことが、モジュール設計の基本です。
よくある使い方と注意点
CLIやデモの起動に使う
シンプルなコマンドラインツールも、ガードを使えば1ファイルで完結します。
引数処理にはargparse
を使うのが一般的です。
# ファイル名: cli_hello.py
# 簡易CLI: --name で挨拶相手を指定できる
import argparse
def main() -> int:
parser = argparse.ArgumentParser(description="挨拶を出力するCLI")
parser.add_argument("--name", default="world", help="挨拶する相手の名前")
args = parser.parse_args()
print(f"Hello, {args.name}!")
return 0
if __name__ == "__main__":
# main() の戻り値を終了コードとして返す。慣例的に raise SystemExit(...) もよく使われる。
raise SystemExit(main())
$ python cli_hello.py
Hello, world!
$ python cli_hello.py --name Alice
Hello, Alice!
printで__name__の値を確認する
挙動が不安な時は、デバッグ用に__name__
を印字して確認してみましょう。
# ファイル名: debug_name.py
print(f"ここは {__name__} です")
# ファイル名: import_debug_name.py
import debug_name
print(f"import側の __name__ は {__name__}")
$ python debug_name.py
ここは __main__ です
$ python import_debug_name.py
ここは debug_name です
import側の __name__ は __main__
モジュール側は自分の名前、実行主体は常に “__main__”という関係が見えます。
インデントやコロンの書き忘れに注意
よくあるエラーは以下の通りです。
特にダブルアンダースコアとコロンの付け忘れに注意してください。
# 悪い例1: コロンの付け忘れ
if __name__ == "__main__"
print("動かない例")
# 実行時のエラー例
File "bad_syntax.py", line 2
if __name__ == "__main__"
^
SyntaxError: expected ':'
# 悪い例2: アンダースコアの数を間違える
if _name_ == "__main__":
print("動かない例")
# 実行時のエラー例(NameError)
NameError: name '_name_' is not defined
# 正しい例: コロン・インデント・ダブルアンダースコアを正確に
if __name__ == "__main__":
print("OK")
正しくは「前後にダブルアンダースコア」+「==」+「文字列 ‘__main__’」+「末尾のコロン」です。
まとめ
if __name__ == "__main__"
: は「直接実行された時だけ処理を動かすための標準パターン」です。
これを守ることで、次の利点が得られます。
- import時に副作用が走らないため、再利用性とテストのしやすさが向上します。
- サンプル実行やCLI起動など、スクリプトとしての振る舞いを安全に書き分けられます。
- エントリーポイントを
main()
にまとめれば、見通しの良い構成になります。
最後にもう一度要点です。
「定義はトップレベル、実行はガードの中」。
この習慣を身につけるだけで、Pythonコードの品質と扱いやすさが大きく変わります。