note.nkmk.me

Pythonのif __name__ == '__main__'の意味と使い方

Date: 2018-07-29 / tags: Python

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

自作のモジュールでも同じ。例として以下のようなモジュールを作成する。

def func():
    print('Hello!')
    print('__name__ is', __name__)
source: hello.py

__name__は自動的に定義され、モジュール内ではそのまま__name__で取得できる。

このモジュールをインポートして使う。

import hello

print(hello.__name__)
# hello

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

__main__とは

'__main__'はコマンドラインからスクリプトファイルを実行したときに__name__に格納される文字列。

例として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()
source: test_main.py

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

インポートされたモジュールtest_module__name__変数(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__はモジュールの名前が格納されている変数で、コマンドラインからpython(またはpython3)コマンドでスクリプトファイルを実行した場合は__name__変数に'__main__'という文字列が格納される。

  • 他のファイルからインポートされたとき
    • __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__)
source: hello.py

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

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__'が使える。

以下のようなモジュールを作成する。

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

他のスクリプトからインポートして使うことももちろん可能。

import add_module

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

なお、モジュールをコマンドとして使いたい場合は、そのためのスクリプトを別途用意してもOK。

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という名前の関数(main())を定義したからといって自動的にその関数から処理が始まるわけではない。

以下の2つのコードはどちらも同じ実行結果となる。

main()関数を記述。

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

if __name__ == '__main__':
    main()

処理を直接記述。

print('Hello!')

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

python3 hello_main.py
# Hello!

python3 hello_direct.py
# Hello!

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

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事