見出し画像

謎の呪文「if __name__ == '__main__':」

Pythonのサンプルコードをネットで探していると「if __name__ == '__main__'」という謎の呪文が良く出てきます。というか、自分の投稿を見返してみても解説なしに使っていました(笑)

最後の方の「全コード」のところにしれっと入っています。この時の投稿のコードでは、「if~」の一行はあっても無くても正常に動くと思いますが、入れることのメリットもあるので解説していきます。


サンプルコード

sample.1.py

import datetime

def getDatetime():
    now = datetime.datetime.now().strftime('%Y年%m月%d日 %H時%M分')
    print(f'現在は、{now}です。')

if __name__ == '__main__':
    while True:
        getDatetime()   # ①関数の実行
        res = input('継続しますか?(y/) >>>')  # ②ループするか選択
        if res == 'y':
            continue
        else:
            break

getDatetime()という関数を定義しています。この関数が実行されると(①)、現在の日時を取得して「現在は、○年○月○日 ○時○分です。」と表示されます。その後、「継続しますか?」と聞かれる(②)ので「y」を入力すれば継続、その他の文字を入力すれば終了します。

sample2.py

import sample1

sample1.getDatetime()

sample1.pyを「pandas」や「altair」などのモジュールのようにimportしています。そして、sample1で定義したgetDatetime()を実行しています。

直接実行と他ファイルからのimport

これまでやってきたように、コマンドプロンプトで「py sample1.py」と入力するとsample1.pyが実行され上記の解説の通り、現在日時が取得され表示されます。無限ループになっているので、「y」を入力するとループし再度日時が取得されます。

sample2.pyを実行すると、以下のようになります。

sample2.pyでは、関数部分は実行され日時取得されますが、そこでスクリプトは終了しループしません。

どういうこと?

Pythonファイルを実行すると、そのファイル全体がスクリプトとして処理されます。このとき、Pythonは特別な変数 __name__ をセットします。
ファイルが直接実行されると、__name__ は '__main__' に設定されます。従って、sample1.pyを直接実行すると「if~」はTrueとなり、「if~」以下に記述されたループ処理が実行されたということになります。

一方、sample2.pyを実行した時のように、他のファイルからimportされた場合には、__name__ はそのモジュール名に設定されます。従って、「if~」はFalseとなるためループ処理はされません。

検証のため、sample1.pyを少し変更し__name__に何が入っているか分かるようにしてみましょう。

import datetime

def getDatetime():
    now = datetime.datetime.now().strftime('%Y年%m月%d日 %H時%M分')
    print(f'現在は、{now}です。')

print(f'①__name__は{__name__}です')   # 追記①:「if~」前の__name__

if __name__ == '__main__':
    while True:
        getDatetime()
        print(f'②__name__は{__name__}です')  # 追記②:「if~」がTrueの時の__name__
        res = input('継続しますか?(y/) >>>')
        if res == 'y':
            continue
        else:
            break
else:
    print(f'③__name__は{__name__}です')  # 追記③:「if~」がFalseの時の__name__

sample1.pyを実行すると、以下のようになります。

直接実行なので①の__name__は当然'__main__'となり、「if~」はTrueなので「if~」以下が実行されるためgetDatetime()が実行され、②の'__main__'もprintされたのちに継続可否の分岐に繋がります。

sample2.pyを実行すると、このようになります。

sample1.pyがimportされた段階で①のprintが実行されますが、この場合はモジュール名が入るので'sample1'となっています。従って、「if~」はFalseとなるため、else以下に記述したスクリプトが実行され③の__name__がprintされます。その後、getDatetime()が単発で実行されます。



このように「if __name__ == '__main__':」を用いると、コードが直接実行された場合と、モジュールとしてimportされた場合で処理を分けることができます。そうすることで、コードの再利用性が高まり何度も同じコードを書かなくても良くなります!

いいなと思ったら応援しよう!