結論:型・選択肢・ヘルプをargparseへまとめる
入力条件を変えるたびにソースを書き換える代わりに、argparseでコマンドライン引数を定義する。位置引数、名前付きオプション、型変換、選択肢をまとめられ、使い方を示すヘルプも自動で作れる。入力を受け取った後の処理へ誤った値を流さず、入口で分かる説明を返すのが使いやすいCLIの基本である。
複数の操作を持つ道具なら、サブコマンドで役割を分ける方法がある。この例はsummaryという操作へ数値一覧を渡し、meanかsumを選んで結果を表示する。小さな例だが、後からvalidateやconvertなどを追加する入口にもなる。単一機能しかないプログラムへ無理にサブコマンドを増やす必要はなく、利用者が指定しやすい粒度を選ぼう。
そのまま動かせる例
以下をexample.pyへ保存し、python example.py summary 1 2 3 --mode mean --digits 2として実行する。ここでpythonは普段使っているPythonの実行コマンドに読み替える。掲載した実行結果はこの引数で得られた出力である。標準ライブラリだけを使い、–outputを指定しない限りファイルは作らない。
python example.py --helpでは全体の説明、python example.py summary --helpではsummaryの引数を表示する。これらのヘルプ、正常なsum、誤ったmode、不正な数値、桁数の範囲外も実行して確認した。エラー時の細かい文言や色表示はPython版で変わる場合があるが、この例の実行環境では引数エラーは終了コード2になる。
import argparse
import math
from pathlib import Path
def finite_float(text):
value = float(text)
if not math.isfinite(value):
raise argparse.ArgumentTypeError("finite number required")
return value
def digits_type(text):
value = int(text)
if not 0 <= value <= 6:
raise argparse.ArgumentTypeError("digits must be 0..6")
return value
def make_parser():
parser = argparse.ArgumentParser(prog="measure", description="Summarize numbers")
commands = parser.add_subparsers(dest="command", required=True)
summary = commands.add_parser("summary", help="calculate sum or mean")
summary.add_argument("values", nargs="+", type=finite_float, help="finite numbers")
summary.add_argument("--mode", choices=["mean", "sum"], default="mean")
summary.add_argument("--digits", type=digits_type, default=2)
summary.add_argument("--output", type=Path, help="write a new UTF-8 file")
return parser
def main(argv=None):
args = make_parser().parse_args(argv)
value = sum(args.values)
if args.mode == "mean":
value /= len(args.values)
text = f"result={value:.{args.digits}f}\n"
if args.output is None:
print(text, end="")
else:
with args.output.open("x", encoding="utf-8") as stream:
stream.write(text)
if __name__ == "__main__":
main()
実行結果
result=2.00
位置引数とオプションを使い分ける
valuesは必ず一つ以上必要な位置引数なので、nargs=”+”とした。–modeは省略時にmeanを使い、choicesへない指定を受け付けない。–digitsは整数への変換だけでなく0〜6という範囲も調べる。type=intやtype=floatだけでは業務上の条件まで確認できないので、必要な制約を専用の変換関数で追加するとよい。
floatはnanやinfといった非有限値も解釈できるため、例ではmath.isfiniteも使う。整数変換ができることと、使ってよい回数や桁数であることも同じではない。エラーを見つけたらArgumentTypeErrorで利用者向けの短い説明を返す。変換関数の中で本処理や外部通信を始めず、検証だけに留めると動作を追いやすい。
結果出力とログを分ける
–outputを付けない場合は結果だけを標準出力へ流す。この形なら他のコマンドやプログラムが結果を受け取りやすい。進捗をprintで同じ出力へ混ぜると、機械的な読込を壊す場合がある。調査情報はloggingなどで別の出力先へ分け、正常な結果の形式を安定させたい。ヘルプと引数エラーも処理結果とは役割が異なる。
–outputへパスを渡した場合はUTF-8の新規ファイルを作る。openのxモードなので既存ファイルがあれば上書きしない。type=Pathは文字列をPathにするだけで、書込権限や親フォルダーの存在まで保証するわけではない。ファイルを開く段階でのOSErrorなどは別の失敗として扱い、必要なら原因と保存先を適切に案内する。
テストしやすい入口を作る
mainがargvを受け取れるため、通常の実行以外にも引数リストを渡して動作を確認できる。計算ロジックが大きくなるならさらに関数へ切り出し、引数解析と実際の処理を分けるとよい。parse_argsはヘルプやエラー時にSystemExitで終了する仕様なので、テストでは終了コードも確認する。コードの途中で何度もsys.argvを読み直すより、入口で確定した値を渡す方が追いやすい。
シェルの引用符はOSや実行環境で違う。空白のあるファイルパスや負の数の扱いは、実際の利用環境でヘルプと合わせて試そう。今回はLinuxのPythonで引数解析を実行確認しており、全シェルでの入力方法を保証するものではない。引数が増えて長くなる場合は、TOMLなどの設定ファイルへまとまった条件を分離する方法も検討できる。
確認環境と参考資料
例はLinux・CPython 3.12.14で実行した。掲載した出力はこの環境での結果である。公式資料のstable版や最新版は更新されるため、手元のバージョンと対応する仕様も確認してほしい。
- Python公式:argparse(2026年10月2日参照)
関連項目:printからloggingへ:重要度と例外の記録を使い分ける / TOML設定ファイルをtomllibで読み込み、入力ミスを早めに見つける / subprocess.runで外部コマンドの失敗・出力・時間切れを扱う
