Python逆引き:実行時に最初に呼び出される関数を指定したい

備忘録ヘッダ画像 逆引きソースコード

他の言語でいうところのエントリポイントのような関数が欲しいときは、__name__ をうまく使うといい。

コード

以下のようにif name == "main":をインデントが無い部分に追加し、__name__変数が"__main__"であった場合に、最初に呼び出したい関数をコールする処理を追加する。
これで、このコードを直接実行する際はmain関数から処理を始めるような動きにできる。

def main():
    print("最初に呼び出される関数。")
    
if __name__ == "__main__":
    main()

なんでこんな動きになるの?

__name__はPythonの特殊な変数で、モジュールがどのようにロードされたかに関する情報を提供している。
この変数はモジュールが直接実行された場合には文字列:"__main__" として初期化され、他のモジュールからインポートされた場合にはモジュール自身のPythonファイル名から.pyを消した名前が入る。

例えば、以下のような構造のスクリプトを考えてみる。

def main():
    print("main関数が呼び出されました。")

if __name__ == "__main__":
    main()

このsample_script.pyは、直接実行された場合に main 関数を呼び出す。
しかしsample_scriptモジュールが他のモジュールから import された場合、__name__変数が"__main__"ではなくなるのでmain関数が勝手に呼び出される事は無い。

例えば、sample_script をimportする以下another_script.pyがあった場合

import sample_script
sample_script.main()

この場合、sample_scriptの__name__はモジュール名の”sample_script”となっているため、if文以下のコードは実行されない。
このように__name__を利用する事で、モジュールがスクリプトとして実行されたか、他のモジュールからインポートされたかを判断しそれに応じて適切なコードを実行できる。
うまく使って他のスクリプトから呼び出されても大丈夫な、再利用可能なモジュールを作ろう。

ちなみに

ちなみにif __name__== "__main__" 以下の部分にはあまり多くののコードを書かない方がいいらしい。
例えばここで変数を定義すると、そのモジュールにとってのグローバル変数になってしまい、意図しないアクセスをしてバグの原因になるかもしれない。
コード例のようにmain関数を用意してあげるのが可読性の観点でも良いと思う。

タイトルとURLをコピーしました