【Python】if __name__ == ‘__main__’ とは

if __name__ == '__main__'の意味合いの解説ページアイキャッチ

このページでは、Python スクリプトでよく見る if __name__ == '__main__' の意味について解説していきます。

書籍やネット上で公開されている Python スクリプトでは下記のように if __name__ == '__main__' が利用されていることが多いです。

利用例

def main():
    # 略

if __name__ == '__main__':
    main()

これを真似て、上記のように if __name__ == '__main__' を利用してスクリプトを記述している方も多いのではないのでしょうか?

でも、単に真似て記述しているだけで、if __name__ == '__main__' の意味合いを理解していない方も多いのではないかと思います。

このページでは、if __name__ == '__main__' の意味や if __name__ == '__main__' を利用するメリットについて解説をしていきたいと思います。

__name__ とは

まず、単純に考えると、if __name__ == '__main__'__name__ の参照する文字列が '__main__' であるかどうかを判断する if 文になります。

この '__main__' は単なる文字列です。

では __name__ とは何なのでしょうか?この点を深掘りしていきたいと思います。

__name__ を出力してみる

この __name__ の意味合いを理解するために、ここで2つのスクリプトを用意し、実際に __name__ の出力結果を確認していきたいと思います(2つのスクリプトは同じフォルダ内に用意してください)。

直接スクリプトを実行した時の出力結果

まず1つ目に用意するのが、下記の MyCalc.py になります。

MyCalc.py

def add(x, y):
    return x + y

def sub(x, y):
    return x - y

def mul(x, y):
    return x * y

def div(x, y):
    return x / y

print(__name__ + ' START!')
print(add(5, 2))
print(sub(5, 2))
print(mul(5, 2))
print(div(5, 2))

スクリプトを見ていただければ分かるように、MyCalc.py では addsubmuldiv の4つの関数を定義しています。

また、ご存知の通り、Python スクリプトではファイルの上側の行の処理から順に実行されていくことになります。ただし、関数やクラスの定義に関しては読み込まれるだけで、実行されるのは関数やクラスの定義以外の行の処理となります。

そして、その実行される行で関数やメソッドの呼び出しが行われる際に、そこで初めて関数やクラス内の処理が実行されることになります。

Pythonでの処理の実行順を示す図

つまり、MyCalc.py において最初に実行されるのは下記の行の処理となります。この行では、今回注目している __name__  の出力を行なっています。

最初に実行される行

print(__name__ + ' START!')

そして、それ以降の行で定義した関数呼び出しが行われることで、関数内の処理が実行されることになります。

具体的には、MyCalc.py 内で定義した addsubmuldiv の4つの関数に対して引数 x = 5y = 2 を指定して実行し、その結果の出力を行なっています。

では、この MyCalc.pypython コマンドで実行してみましょう!

結果は下記のようになるはずです。

% python MyCalc.py 
__main__ START!
7
3
10
2.5

計算結果も上手く表示されているのですが、それよりも注目していただきたいのが __name__  の出力結果です。

上記からも確認できるように、print(__name__ + ' START!') の出力結果が __main__ +  START! となっているため、__name__ の出力結果は '__main__' であることが確認できます。

import してスクリプトを実行した時の出力結果

2つ目に用意するのが、下記の MyMain.py になります。

MyMain.py

import MyCalc

print(__name__ + ' START!')
print(MyCalc.add(10, 3))
print(MyCalc.sub(10, 3))
print(MyCalc.mul(10, 3))
print(MyCalc.div(10, 3))

MyMain.py では、1行目で先ほど用意した MyCalc.py をモジュールとして import しています。このように、Python においては自身で作成したスクリプトも import してモジュールとして利用することが可能です。

MyCalc.pyをMyMain.pyからimportする様子

import 後は、__name__ の出力および MyCalc で定義された関数の実行結果の出力を行なっています。

では、この MyMain.pypython コマンドで実行してみましょう!

結果は下記のようになるはずです。

% python MyMain.py 
MyCalc START!
7
3
10
2.5
__main__ START!
13
7
30
3.3333333333333335

計算結果は置いておくとして、ポイントになるのが __name__ の出力結果です。

MyMain.py を実行した場合、__name__ の出力は2回行われることになります。

まず import MyCalc が実行されることによって、MyCalc.py で定義されている関数の読み込み&下記の行の実行が行われます。

import時に実行される処理

print(__name__ + ' START!')
print(add(5, 2))
print(sub(5, 2))
print(mul(5, 2))
print(div(5, 2))

import 時には関数やクラスの定義の読み込みが行われ、これにより、import したモジュールの関数やクラスを利用することができるようになります。

ただし、関数やクラスの定義以外の処理に関しては実行されてしまいます。実はここが if __name__ == '__main__' を利用するメリットにつながってきます(詳細は後述で解説します)。

具体的には、import MyCalc を実行すれば、関数定義以外の上記の5行が実行されることになります。

そして、上記の1行目での print の実行結果が、先ほどの MyMain.py 実行結果の下記部分となります。

MyCalc START!

つまり、MyCalc.py からの __name__ の出力結果は 'MyCalc' となっています。

直接スクリプトを実行した時の出力結果MyCalc.py を実行した時とは結果が違いますね…。直接スクリプトを実行した時の出力結果 で実行した際には __name__ の出力結果は '__main__' となっていたはずです。

なぜ、今回と 直接スクリプトを実行した時の出力結果 の時とで出力結果が異なるのでしょうか?

その理由は MyCalc.py の実行の仕方の違いにあります。

直接スクリプトを実行した時の出力結果 の時は、MyCalc.py を python コマンドで直接実行していました。そして、その結果 __name__ の出力結果が '__main__' となっていました。

それに対し、今回は MyCalc.py を MyMain.py から import することによって実行しています。この MyCalcimport 時に指定された モジュール名 となります。そして、その結果、__name__ の出力結果が 'MyCalc' となりました。

つまり、スクリプトが python コマンドで直接実行された場合、__name__'__main__' の文字列を参照することになります。

それに対し、他のスクリプトから import されて実行された場合、__name__'モジュール名' の文字列を参照することになります。

importされた場合と直接実行された場合の__name__が参照する文字列の違いを示した図

では、ここで先ほどの実行結果における2回目の __name__ の出力内容を確認してみましょう!この 2回目の __name__ の出力は MyMain.py から実行されており、この出力結果は先ほどの MyMain.py 実行結果の下記部分となります。

__main__ START!

MyMain.pypython コマンドによって直接実行されているため(python ファイル名.py によって実行されているため)、__name__ は  '__main__' を参照しており、__name__ の出力結果は上記のように '__main__' となります。

スポンサーリンク

__name__ が参照する文字列

ここまで確認してきたように、__name__ はスクリプトの「実行のされ方」に応じて下記を参照する変数となります。

  • import されて実行された場合:'モジュール名'
  • python コマンドで直接実行された場合:'__main__'

また、import されて実行されるということは、そのスクリプトがモジュールとして利用されていることになります。したがって、上記の2つの場合分けは、スクリプトがモジュールとして利用されるかどうかの観点で下記のように書き換えることもできます。

  • モジュールとして利用されているスクリプトの場合:'モジュール名'
  • モジュールとして利用されていないスクリプトの場合:'__main__'

おそらく、if __name__ == '__main__' のメリットを理解する上では、上記のモジュール利用の観点での __name__ の意味合いで考えた方が分かりやすいと思います。

if __name__ == '__main__' とは

__name__ の変数の役割ができれば、if __name__ == '__main__' の意味合いも簡単に理解できると思います。

前述の通り、__name__ は下記を参照する変数となります。

  • モジュールとして利用されているスクリプトの場合:'モジュール名'
  • モジュールとして利用されていないスクリプトの場合:'__main__'

したがって、if __name__ == '__main__' とは、この if 文を記述しているスクリプトが「モジュールとして利用されていない」ことを判断するための条件文であると言えます。

ですので、if __name__ == '__main__' が成立する場合、このスクリプトは「モジュールとして利用されていない」と判断することができます。

__name__=='__main__'の成立とモジュール利用との関係性を示す図

逆に if __name__ == '__main__' が成立しない場合、もしくは if __name__ != '__main__' が成立する場合、このスクリプトは他のスクリプトから「モジュールとして利用されている」と判断することができます。

つまり、下記のように条件分岐を行えば、モジュールとして利用されていない場合のみ(python コマンドによって直接実行されている場合のみ)、特定の処理 を実行することができるようになります。

モジュールとして利用されていない場合のみ処理を実行

if __name__ == '__main__':
    特定の処理

また、下記のように条件分岐を行えば、他のスクリプトからモジュールとして利用されている場合のみ、特定の処理 を実行することができるようになります。

モジュールとして利用されている場合のみ処理を実行

if __name__ != '__main__':
    特定の処理

もちろん、両方の場合を考慮して下記のように条件分岐を行なっても良いです。

モジュールとして利用されている場合のみ処理を実行

if __name__ == '__main__':
    モジュール利用されていない場合のみ実行したい処理
else:
    モジュール利用されている場合のみ実行したい処理

if __name__ == '__main__' を利用するメリット

では、if __name__ == '__main__' を利用するメリットは何なのでしょうか?

このメリットは、if __name__ == '__main__' の意味合いからも分かるように、モジュールとして利用されているかどうかによってスクリプト実行時の動作を切り替えることができるようになる点にあります。

スポンサーリンク

利用しやすいモジュールを実現できる

ご存知の通り、Python では import によって他のモジュールで定義された機能(関数やクラス)を利用することができるようになります。

ほとんどの場合、import する目的は、import するモジュールで定義された関数やクラスを利用することであると言えると思います。

モジュールで定義されている関数やクラスを利用したくてimportを行う様子

それに対し、モジュールの作り方によっては、import すると関数やクラスの定義の読み込みだけでなく、処理の実行までされてしまうような場合があります。

前述の MyCalc.py がまさにそれで、import MyCalc を行うことで addsubmuldiv の4つの関数が利用できるようにもなるのですが、それに追加して import 時に下記の処理まで実行されてしまいます。

モジュール利用時の無駄な処理

print(__name__ + ' START!')
print(add(5, 2))
print(sub(5, 2))
print(mul(5, 2))
print(div(5, 2))

ですので、addsubmuldiv を利用することのみを目的に import MyCalc を実行した場合、import 時に上記の処理まで実行され、無駄な処理・出力が行われてしまうことになります。

関数を使いたいだけなのに不要な処理まで実行されてしまう様子

このように、モジュール利用時には実行されない方が良い処理が存在する場合、if __name__ == '__main__' を利用することで、そういった処理をモジュールとして利用されている場合のみスキップするようにすることができます。

例えば MyCalc.py の例であれば、上記の5行の処理を次のように if __name__ == '__main__' が成立する場合のみ実行するようにしてやれば、import されて他のスクリプトからモジュールとして利用される場のみ、これらの処理をスキップするようにすることができます。

無駄な処理のスキップ

def add(x, y):
    return x + y

def sub(x, y):
    return x - y

def mul(x, y):
    return x * y

def div(x, y):
    return x / y

if __name__ == '__main__':
    print(__name__ + ' START!')
    print(add(5, 2))
    print(sub(5, 2))
    print(mul(5, 2))
    print(div(5, 2))

こうすることで、import 時に無駄な処理が行われないようになり、利用しやすいモジュールとして仕立てることができます。

もちろん、下記のように if __name__ == '__main__' 成立時に実行される処理を main 関数として切り出し、if __name__ == '__main__' 成立時に main 関数の呼び出しのみを行うようにしても良いです。

main関数の切り出し

def add(x, y):
    return x + y

def sub(x, y):
    return x - y

def mul(x, y):
    return x * y

def div(x, y):
    return x / y

def main():
    print(__name__ + ' START!')
    print(add(5, 2))
    print(sub(5, 2))
    print(mul(5, 2))
    print(div(5, 2))

if __name__ == '__main__':
    main()

この形式が if __name__ == '__main__' の利用例としては一番ポピュラーだと思いますが、別に if __name__ == '__main__' 成立時に実行される処理を関数として切り出したり、関数名を main とすることは必須ではありません。

重要なのは、モジュールとして利用されているかどうかによって動作を切り替えることです。ただ、上記の形式は見慣れている方も多いと思いますので、慣例に倣って上記の形式で記述してあげる方が無難だと思います。

モジュールの単体テストが実現できる

無駄な処理なのであれば、わざわざ if __name__ == '__main__' を利用しなくても削除してしまえば良いと思われる方もいるかもしれません。

もちろんそういったケースもあると思いますが、モジュールとして利用されない場合に意味のあるものとなる処理もあり、この場合は if __name__ == '__main__' を利用した方が良いと思います。

その処理の具体例としては、モジュールで定義された関数やクラスの動作確認を行う処理が挙げられると思います。要はモジュールの単体テストです。

__name__=='__main__'の有効利用例

いくら関数やクラスの提供を行うことを目的としたモジュールを開発するといっても、それらの関数やクラスの動作確認は行うはずです。

そういった、モジュールの動作確認を行う際の処理を同一スクリプト内に記述したい場合は if __name__ == '__main__' の利用が効果的です。if __name__ == '__main__' が成立する場合のみモジュールの単体テストが実行されるようにしておけば、python コマンドによって直接実行された場合のみモジュールの単体テストが実行されるようになります。

こうしておくことで、モジュール開発者はモジュールのスクリプトを python コマンドで直接実行することで動作確認を行うことができ、モジュール利用者は import で実行することで動作確認という不要な処理をスキップすることができるようになります。こんな感じで、if __name__ == '__main__' を利用することでスクリプトの実行の仕方によって動作を切り替えることができます。

実行の仕方によってモジュールの通常利用と単体動作確認とを使い分ける様子

例えば、利用しやすいモジュールを実現する の最後に紹介した MyCalc.py では、関数を実行する処理(関数の動作確認を行う処理)が if __name__ == '__main__' が成立する場合のみ実行されるようになっているため、動作確認を行いたい場合は python コマンドで直接実行してやれば良いことになります。

また、下記のように MyCalc.py を書き換えれば、python コマンドで実行した場合のみ関数内の print が実行されるようになります。したがって、モジュールとして利用される時の動作に(ほぼ)影響を与えることなく、モジュールの単体テスト時に詳細な動作確認を行うことができるようになります。

詳細なログ表示

def add(x, y):
    if DEBUG_MODE:
        print('引数:', x, y)

    return x + y

def sub(x, y):
    if DEBUG_MODE:
        print('引数:', x, y)

    return x - y

def mul(x, y):
    if DEBUG_MODE:
        print('引数:', x, y)

    return x * y

def div(x, y):
    if DEBUG_MODE:
        print('引数:', x, y)

    return x / y

def main():
    print(__name__ + ' START!')
    print(add(5, 2))
    print(sub(5, 2))
    print(mul(5, 2))
    print(div(5, 2))

if __name__ == '__main__':
    DEBUG_MODE = True
    main()

このように、if __name__ == '__main__' はモジュールとして利用されたかどうかによって実行される処理を切り替える際に有効であり、特に有効な処理としてはモジュールで定義する関数やクラスの動作確認(モジュールの単体テスト)が当てはまると思います。

想定外の使い方をされている場合に警告出力できる

また、if __name__ == '__main__' を利用することで、自身が作成したスクリプトが「想定外の使い方」をされている場合に警告を出力するようなことも可能となります。

これにより、「モジュールとして利用されることを想定しているスクリプト」が python コマンドで直接実行されたような場合に警告を出力するようなことができます。そして、それによってスクリプト利用者に正しい使い方を示すことができ、より使いやすいスクリプト・モジュールに仕立てることができます。

例えば、MyCalc.py を下記のように変更してやれば、import されずに python コマンドで実行された際には警告が出力されるようになり、利用者に正しい使い方を示すことができます。

警告表示

def add(x, y):
    return x + y

def sub(x, y):
    return x - y

def mul(x, y):
    return x * y

def div(x, y):
    return x / y

if __name__ == '__main__':
    print('このスクリプトはimportして使用してください')

スポンサーリンク

if __name__ == '__main__' の使いどころ

最後に、どんな時に if __name__ == '__main__' を利用すれば良いのかについて解説しておきます。

ここまで解説してきたように、if __name__ == '__main__' はモジュールとして利用される場合とそれ以外の場合とで場合分けを行う際に有効な条件分岐となります。

ですので、特にモジュールとして利用されることを見据えて作成するスクリプトにおいては、if __name__ == '__main__' を利用して適切な場合分けを行うようにした方が良いと思います。

ただ、最初はモジュールとして利用されることを見据えていないようなスクリプトであっても、そのスクリプトで定義した関数を後から他のスクリプトから import して利用したくなるような場合も多々あります。

そういった場合のことを考えると、とりあえず if __name__ == '__main__' を使ってモジュールとして利用される場合とされない場合とで適切に動作を切り替えられるようにしておいた方が無難だと思います。こうしておくことで、モジュールとして利用される予定のなかったスクリプトであっても、後からスムーズにモジュールとして利用できるようになります。

ということで、結局、関数定義やクラス定義を行うスクリプトであれば、とりあえず if __name__ == '__main__' を利用しておいた方が良いと言えると思います。

ただ、上記のようなことは if __name__ == '__main__' に限った話ではなく、関数やクラスの作り方にも言える話です。

後からモジュールとして利用されることがあることを考慮して、モジュールとして利用しやすいように関数やクラスも作った方が良いです。

こうすることで、後から自分が作ったスクリプトをモジュールとした再利用しやすくなり、開発効率を向上させることができます。

if __name__ == '__main__' はモジュールとして利用しやすいスクリプトを作成するための手段の一つに過ぎず、if __name__ == '__main__' を使いこなすことよりもスクリプト全体としてモジュール利用しやすい記述を心がけることが重要だと思います。

まとめ

このページでは、Python における if __name__ == '__main__' の意味合いについて説明しました。

__name__ は Python インタプリタによって自動的に用意される変数であり、スクリプトの使い方によって下記のように参照する文字列が変化します。

  • モジュールとして利用されているスクリプトの場合:'モジュール名'
  • モジュールとして利用されていないスクリプトの場合:'__main__'

したがって、if __name__ == '__main__' は、この条件分岐を行なっているスクリプトがモジュールとして利用されていないかどうかを判断するものであると考えることができます。

具体的には、条件が成立する場合はモジュールとして利用されていない、すなわち python コマンドで直接実行されていると判断することができます。逆に条件が成立する場合、そのスクリプトはモジュールとして利用されていると判断することができます。

そして、この判断を行うことで、モジュール利用されているかどうかによってスクリプト実行時の動作を変化させるようなことができます。例えば、モジュール利用されている場合に無駄な処理をスキップするようなことも可能ですし、想定されていない使い方をされている際に警告表示をするようなことも可能です。

if __name__ == '__main__' を利用することで、より使いやすいモジュールを実現することが可能となりますので是非積極的に利用してみてください!

また、if __name__ == '__main__' の利用だけでなく、関数やクラスを作る際にもモジュールとして利用しやすいものを作るように心がけると良いと思います!

同じカテゴリのページ一覧を表示