Pythonのif name == 'main'の意味と使い方

Python初心者がサンプルコードを見たときに理解に苦しむのが、おまじないのように書かれているif name == 'main'。 アンダースコアに惑わされてしまうが「__name__に格納されている値が'main'という文字列である場合に以降の処理を実行する」という単なるif文なので、__name__と'main'の意味が分かれば理解しやすいです。 以下の内容について説明します。

__name__とは 'main'とは if name == 'main'の意味 if name == 'main'の使い方、使いどころ モジュールのテストコードを記述 モジュールをコマンドとして利用 Pythonにおけるmain()関数

なお、Pythonでは文字列リテラルをシングルクォート'でもダブルクォート"でも表せるので、if name == "main"でも同じ意味。

__name__とは

モジュールをインポートするとその__name__属性にモジュールの名前が文字列として格納されます。モジュール名.__name__で取得できます。

import math
import numpy as np

print(math.__name__)
# math

print(np.__name__)
# numpy

自作のモジュールでも同じ。例として以下のようなモジュールhello(hello.py)を作成します。モジュール内で__name__を出力する関数を定義しています。

def func():
    print('Hello!')
    print('__name__ is', __name__)

このモジュールhelloをインポートして使うと以下のようになります。

import hello

print(hello.__name__)
# hello

hello.func()
# Hello!
# __name__ is hello

インポートされたモジュールの__name__にはモジュール名'hello'が格納されていることが分かる。

'main'とは

上述のように、別のファイルからインポートされると__name__にはモジュール名が格納されます。 一方、ファイルをコマンドラインからスクリプトとして実行すると__name__には'main'という文字列が格納されます。

main --- トップレベルのスクリプト環境 — Python 3.7.2 ドキュメント

例としてtest_moduleというモジュール(test_module.py)とそれをインポートして使うtest_main.pyを作成します。

def func():
    print('    This is func() in test_module.py')
    print('    __name__ is', __name__)

if __name__ == '__main__':
    print("Start if __name__ == '__main__'")
    print('call func()')
    func()


import test_module

print('This is test_main.py')
print('test_module.__name__ is', test_module.__name__)

print('---')
print('call test_module.func()')

test_module.func()

test_main.pyをコマンドラインからpython(またはpython3)コマンドで実行すると以下のような結果となります。

python3 test_main.py
# This is test_main.py
# test_module.__name__ is test_module
# ---
# call test_module.func()
#     This is func() in test_module.py
#     __name__ is test_module

helloの例と同様に、インポートされたモジュールtest_moduleの__name__にはモジュール名'test_module'が格納されています。 一方、test_module.py自体をコマンドラインから実行すると以下のような結果となります。

python3 test_module.py
# Start if __name__ == '__main__'
# call func()
#     This is func() in test_module.py
#     __name__ is __main__

__name__には'main'という文字列が格納され、if name == 'main':以降の処理が実行されていることが分かる。 このように、他のファイルからインポートされた場合は__name__に'モジュール名'が格納され、コマンドラインからpython(またはpython3)コマンドで実行された場合は__name__に'main'という文字列が格納されます。 なお、pythonコマンドに-mオプションをつけてモジュールとして実行する場合やインタラクティブモードでも__name__には'main'という文字列が格納されます。

python3 -m test_module
# Start if __name__ == '__main__'
# call func()
#     This is func() in test_module.py
#     __name__ is __main__

if name == 'main'の意味

まとめると、__name__に格納される値は以下の通り。

他のファイルからインポートされたとき __name__は 'モジュール名' そのファイル自体がpython(またはpython3)コマンドでスクリプトとして実行されたとき __name__は'main'したがって、if name == 'main'は「該当のファイルがコマンドラインからスクリプトとして実行された場合にのみ以降の処理を実行する」という意味となります。他のファイルからインポートされたときは処理は実行されません。

if name == 'main'の使い方、使いどころ

if name == 'main'を使うと、モジュールのテストコードを記述したり、モジュールをコマンドとして利用できるようにしたりすることができます。

モジュールのテストコードを記述

モジュールの関数の出力結果を確認したいというような場合に、if name == 'main'以下にテストコードを書いておく。 例えば上述のhello.pyの場合です。

def func():
    print('Hello!')
    print('__name__ is', __name__)

関数が定義されているだけなので、このファイルをコマンドラインから実行してもなにも起こらない。

python3 hello.py


if __name__ == '__main__'を追加します。
def func():
    print('Hello!')
    print('__name__ is', __name__)

if __name__ == '__main__':
    func()

これをコマンドラインから実行すると、if name == 'main'以下のコードに従ってモジュール内の関数が実行されます。

python3 hello_if_name.py
# Hello!
# __name__ is __main__

他のファイルからインポートされた場合はif name == 'main'以下のコードは実行されないので、余計な処理が発生することはない。

モジュールをコマンドとして利用

モジュールをコマンドとして利用したい場合にもif name == 'main'が使えます。 以下のようなモジュールを作成します。

import sys

def add(a, b):
    return a + b
if __name__ == '__main__':
    print(add(float(sys.argv[1]), float(sys.argv[2])))

if name == 'main'以下ではsys.argvでコマンドライン引数を取得しモジュール内の関数に渡しています。

sys.argvはコマンドライン引数のリストで最初の要素sys.argv[0]はスクリプト名となります。また、文字列として格納されるので数値として扱いたい場合はint(), float()などで変換します。 これによって、コマンドラインから引数をつけて実行した場合、モジュール内の関数が処理されます。

python3 add_module.py 1.2 3.4
# 4.6

他のファイルからインポートして使うことももちろんできます。この場合はif name == 'main'以下のコードは実行されません。

import add_module

print(add_module.add(100, 200))
# 300

なお、モジュールをコマンドとして使いたい場合は、そのためのファイルを別途用意しても問題ありません。

import sys
import add_module

print(add_module.add(float(sys.argv[1]), float(sys.argv[2])))

これを実行した結果は以下の通り。

python3 add_module_command.py 1.2 3.4
# 4.6

この場合、if name == 'main'は必要ない。 特にargparseモジュールなどを使ってコマンド化する場合は別のファイルにしたほうがスッキリします。

import argparse
import add_module

parser = argparse.ArgumentParser()
parser.add_argument('a', type=float)
parser.add_argument('b', type=float)

args = parser.parse_args()
print(add_module.add(args.a, args.b))

これを実行した結果は以下の通り。

python3 add_module_argparse.py 1.2 3.4
# 4.6

Pythonにおけるmain()関数

ついでにPythonにおけるmain()関数にも触れておく。 PythonではC言語のようにmain()関数から処理が実行されるというわけではなく、mainという名前の関数を定義したからといって自動的にその関数から処理が始まるわけではない。 以下の2つのコードはどちらも同じ実行結果となります。 main()関数を記述。

def main():
    print('Hello!')

if __name__ == '__main__':
    main()

処理を直接記述。

print('Hello!')

コマンドラインから実行したときの結果は同じ。

python3 hello_main.py
# Hello!

python3 hello_direct.py
# Hello!

特に大規模なプログラムの場合は慣例として起点となる関数をmain()という名前にしておくことが多いが、これはあくまでも分かりやすさのためで、仕様として特別な意味はないし、必須でもない。

Last Updated: 6/26/2019, 10:48:26 PM