概要
Pythonのコードでif __name__ == '__main__':
というIF文をたまに見かけますよね。Djangoならmanage.py
で見ます。
これってどういう挙動なんだ?って思ったのでサンプルコードで作って確認してみました。
サンプルコード
def say_hello():
print("もちろんこれも直接実行の時だよ!")
print("これはいつでも表示されるぞ!")
if __name__ == '__main__':
print("これは直接実行される時だけ表示されるよ!")
say_hello()
def sample_function():
print(__name__)
sample_function()
スクリプト実行とモジュールとしての読み込みとは?
上記のスクリプトを実行すると以下が出力されます。
python3 module_example.py
↓
これはいつでも表示されるぞ!
これは直接実行される時だけ表示されるよ!
もちろんこれも直接実行の時だよ!
__main__
では、別のスクリプトからモジュールとしてインポートした場合はどうなるのでしょうか?
import module_example
上記の実行結果は以下になります。
python3 another_script.py
↓
これはいつでも表示されるぞ!
module_example
まず、上3つの日本語のテキストが一つだけになりました。
「これは直接実行される時だけ表示されるよ!」
と
「もちろんこれも直接実行の時だよ!」
が出力されていないことがわかります。
つまり、if __name__ == '__main__':
ブロックを使用することで、そのスクリプトが直接実行された時のみに実行してほしいことの制御を行うことができるのです。
出力されなくなった2つのテキストはどちらも、if __name__ == '__main__':
がTrue
だった場合に実行されるものです。しかし、よそからスクリプトを読み込まれた場合(モジュールとして読み込まれた場合)はこれが実行されない、ということです。
ではこのIF文のTrue
とかFalse
になる意味をもう少し考えてみます。
ここで、一番下に出力されていた__main__
とかmodule_example
が関係してきます。
上述のif __name__ == '__main__':
というIF文とその結果をみて察しがつくと思いますが、モジュールとして読み込まれた場合はモジュール名が格納され、直接スクリプトとして実行された場合は「__main__
」になるのです。
つまり、結論以下のようになります。
・スクリプト実行された場合は、__name__
は__main__
である。
であるので、if __name__ == '__main__':
がTrue
になり、そのブロックが実行される。
・モジュールとしてインポートされて実行された場合は、__name__
はモジュール名
である。
であるので、if __name__ == '__main__':
がFalse
になり、そのブロックが実行されない。
ちなみに、スクリプトが直接実行されるような状態のことを 「トップレベルのスクリプト環境」("Top-level code"
)というらしいです。
main --- トップレベルのスクリプト環境 — ...
main is the name of the environment where top-level code is run. "Top-level code" is the first user-specified Python module that starts running. It's "top-level" because it imports all other modules that the program needs. Sometimes "top-level code" is called an entry point to the application.
参考1: djangoのmanage.py
冒頭でも紹介した通り、djangoのmanage.py
では、if __name__ == '__main__':
ブロックを見ることができます。
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
ちなみにdef main()
は特に何か特別な意味があるわけではなく、プログラミング慣習としてメインプログラムの初めに使うことがある、というイメージです。こういうのをエントリポイント(プログラムの処理の開始地点)と呼ぶらしいです。「どこがこのプログラムのはじめなんだ!?」ということがわかるように、可読性を高める役割があるんですね。
main()
でなくてもなんでも良いですが、他のプログラミング言語で使うことが多い?らしいからPythonでもそうしているっぽい。
参考2: __main.py__
とは?
似たような概念に__main.py__
というファイルがあります。
こちらは以下の記事で紹介していますので、よかったらどうぞ。
【Python】「main.py」とは何か?このファイルから他のモジュールを実行する方法