ネットで見つけた Python スクリプトや、自分で書いた Python スクリプトの中で、 「if name == “main“` 」という記述をよく目にします。
Pythonのプログラムを実行する際に、なぜこのif文を使っているのでしょうか?この記事では、if文の使い方の仕組み、利点、使える場所について説明します。
평평평평평평평평평평
name__`属性はデフォルトで現在のローカルスコープにある名前の1つです。
Pythonスクリプトを実行するときや、コードをモジュールとしてインポートするときに、Pythonインタープリターが自動的にこの値を追加します。
Pythonインタプリタ上で次のコマンドを試してみてください。
dir()の属性リストに
name` が含まれていることがわかるかもしれません。
dir()
Pythonの __name__
は、クラス名、カレントモジュール名、スクリプト名を定義する特殊な変数で、この変数が呼び出されたときに、そのクラスが実行されます。
name_scriptsという名前の新しいフォルダーを作成し、これがどのように機能するかを理解するためにいくつかのスクリプトを書きます。
そのフォルダーにscript1.py` という新しいファイルを作成し、次のコードを記述します。
print(f'The __name__ from script1 is "{__name__}"')
これは曲者です。
ファイル名は script1
になると思っていました。
デフォルトでは、スクリプトが実行されると、インタプリタはスクリプトを読み込んで、文字列 __main__
を __name__
キーワードに代入します。
上のスクリプトが他のスクリプトにインポートされると、さらに面白いことになります。
次のようなコードを持つ script2.py
という名前の Python ファイルを考えてみましょう。
import script1 # The print statement gets executed upon import
print(f'The __name__ from script2 is "{__name__}"')
見ての通り、このスクリプトを実行すると、出力はスクリプトの名前を示す script1
として与えられます。
最後のprint文はscript2
のスコープにあり、それが実行されると、出力は次のように表示されます。
と表示されます。
Pythonが__name__
スコープをどのように使用し、どのような場合に” _main_pathy” という値を与えるかを理解した上で、なぜコードを実行する前にその値を確認するのかを見ていきましょう。
if ■■ == “■■■” in Action
if ステートメントを使用して、このプログラムがメインプログラムとして実行される場合のみ、 コードブロックが実行されるようにしました。
これによって、プログラムはそれ自体で実行可能でありながら、コードを実行せずに機能をインポートしたい他のPythonモジュールに友好的です。
次のようなPythonのプログラムを考えてみましょう。
a) script3.py
は add()
という関数を含んでおり、メインコンテキストからのみ呼び出されます。
def add(a, b):
return a+b
if __name__ == "__main__":
print(add(2, 3))
以下は script3.py
が呼び出されたときの出力です。
スクリプトが直接実行されたので、__name__
キーワードは __main__
に割り当てられ、 if __name__ == "__main__"
の条件下でコードのブロックが実行されます。
b) このスニペットが script4.py
からインポートされると、次のようになります。
import script3
print(f"{script3.__name__}")
if name == “main“の下の
script3.pyのブロックは、期待した通り実行されませんでした。
これは、nameキーワードにスクリプトの名前が代入されているために起こります。
これは、nameキーワードにスクリプトの名前
script3が代入されているためです。
これは、name` キーワードに代入された値を表示する print 文で確認することができます。
How Does _name == “_main_theater” Help in Development?
スクリプトを作成する際に、この if 文を使用するケースをいくつか紹介します。
- テストは、バグを発見するだけでなく、コードが要求されたとおりに動作することを確認するための良い習慣です。テストファイルには、関数やオブジェクトをインポートする必要があります。このような場合、一般的にスクリプトがメインモジュールとして実行されることを望みません。
- ライブラリを作成しているが、ユーザーのためにデモやその他の特別なランタイムケースを含めたいと考えている。この if 文を使うことで、あなたのコードをライブラリとして使用する Python モジュールは影響を受けません。
モジュールのための⾳新ファイルの作成
if name == “main“ブロックは、スクリプトが
mainスコープにあるときに実行される条件となるコードを取得するためのものです。
しかし、Python でパッケージを作成する際には、main` コンテキストで実行されるコードを別のファイルに記述した方がよいでしょう。
次の例では、計算を実行するためのパッケージを考えてみましょう。
このようなシナリオのファイルツリー構造は、次のように視覚化できます。
calc # --> Root directory
├── __main__.py
├── script1.py
├── script2.py
├── script3.py
├── script4.py
└── src # --> Sub-directory
├── add.py
└── sub.py
このツリー構造には、ルートディレクトリである calc
とサブディレクトリである src
が含まれます。
calcディレクトリの下にある
main.py` は、以下の内容を含んでいます。
from src.add import add
from src.sub import sub
a, b = input("Enter two numbers separated by commas: ").split(',')
a, b = int(a), int(b)
print(f"The sum is: {add(a, b)}")
print(f"The difference is: {sub(a, b)}")
add.py
には以下の内容が含まれる。
def add(a, b):
return a+b
そして、sub.py
には以下の内容が含まれています。
def sub(a, b):
return a-b
このスクリプトは calc
ディレクトリの外から実行することができ、__main__.py
内のロジックが実行されます。
python3 calc
この構造では、ワークスペースの場所やディレクトリの構成がすっきりし、エントリポイントも __main__.py
という別のファイルで定義されています。
結論
name == “main“` は、Pythonスクリプトがユーザーから直接実行されるときだけ、コードのブロックを実行します。
これは、コードがモジュールとしてインポートされるのではなく、プログラムとして実行されるときに異なる動作をさせることができるため、強力です。
大きなモジュールを書くときは、モジュールを実行するために __main__.py
ファイルを持つという、より構造化されたアプローチを選択することができます。
スタンドアローンのスクリプトの場合は、 if __name__ == "__main__"
を含めることで、よりシンプルにAPIとプログラムを分離できる方法です。