【Python】「if __name__ == '__main__':」ブロックの意味とは？スクリプト実行とモジュール読み込み

# 概要
Pythonのコードで`if __name__ == '__main__':`というIF文をたまに見かけますよね。Djangoなら`manage.py`で見ます。

これってどういう挙動なんだ？って思ったのでサンプルコードで作って確認してみました。

## サンプルコード

```module_example.py
def say_hello():
    print("もちろんこれも直接実行の時だよ！")

print("これはいつでも表示されるぞ！")

if __name__ == '__main__':
    print("これは直接実行される時だけ表示されるよ！")
    say_hello()

def sample_function():
    print(__name__)    
sample_function()
```

## スクリプト実行とモジュールとしての読み込みとは？

上記のスクリプトを実行すると以下が出力されます。

```
python3 module_example.py
```

↓

```
これはいつでも表示されるぞ！
これは直接実行される時だけ表示されるよ！
もちろんこれも直接実行の時だよ！
__main__
```

では、別のスクリプトからモジュールとしてインポートした場合はどうなるのでしょうか？

```another_script.py

import module_example
```

上記の実行結果は以下になります。

```sh
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__ --- トップレベルのスクリプト環境 — ...](https://docs.python.org/ja/3/library/__main__.html)
 
> __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__':`ブロックを見ることができます。

```manage.py
#!/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__」とは何か？このファイルから他のモジュールを実行する方法](https://qiita.com/Ryo-0131/items/f4c931db885be0e49aac)