はじめに
python の main 関数を使うのは、下記のようなご利益があるが、、
- 再利用性: モジュールとして他のスクリプトやモジュールからインポートしたとき、main関数の中にコードを隔離することで、そのコードが自動的に実行されるの防げる。この構造により、モジュールの関数やクラスを再利用しながら、主要な実行部分をスキップできる。
- 整理と構造: main関数を使うことで、グローバルスコープをクリーンに保ち、コードの構造を整理することができます。これにより、コードの読みやすさと保守性が向上する。
- 引数の処理: argparseなどのライブラリを使って、コマンドラインからの引数を処理する際に、それらの引数をmain関数に直接渡すことができます。
- エラーハンドリング: main関数内で発生するエラーや例外を、関数の外部でキャッチして処理することが容易
- テストの容易性: main関数を使うと、プログラムの主要な部分を独立してテストすることが容易。
実際にコーディングしていると、main関数で使っている変数の中身を ipython や jupyter などで直接アクセスして debug したくなる時がある。その時の方法について紹介します。
2023.10.17 追記
Googleが開発したFireライブラリ
の利用の選択について、@asobinin_kinsan(kinsan asobinin) 様からのご指摘を頂戴しました。Fireライブラリ
を用いた方が、シンプルかつ利便性の良いコードになります。使い方については他の良い記事がありますので、そちらを参考にしてください。
この記事は、argparse が使い慣れている人向け、と解釈ください。
簡単な例
import numpy as np
fname = "test.txt"
pixel = 1
type = 0
def main(fname, pixel, type):
if type > 0:
x = np.arange(pixel)
else:
x = -1 * np.arange(pixel)
return x
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Process data')
parser.add_argument('--fname', type=str, required=True, help='file name')
parser.add_argument('--pixel', type=int, required=True, help='pixel value')
parser.add_argument('--type', type=int, required=True, help='type value')
args = parser.parse_args()
main(args.fname, args.pixel, args.itype)
このようなプログラムを書いているときに、main 関数の中身の x をみたい時がある。
そういう場合は、モジュールとして main 関数を読んで、return される変数を取得すればよいです。
In [1]: from mymodule import main
In [2]: main("a.txt",10,-4)
Out[2]: array([ 0, -1, -2, -3, -4, -5, -6, -7, -8, -9])
In [3]: main("a.txt",10,1)
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
このように、return x の x が戻ってくるので、これで中身を確認できます。
デバッグ時の使い方
return 文はそこで関数が終了、という意味なので、main文が長くて、いろんな変数を使っている場合で、なんか変な変数があり、その中身を見たければ、その変数の近くに return 文を挿入し、他は何も変更せずに実行すると、中身が見ることができて便利です。