閉じる

【Python】argparse入門:コマンドライン引数を最速でマスターする方法

Pythonでスクリプトを書いていると、コマンドライン引数に対応したくなる場面は意外と多いです。

そんなときに強力な味方になるのがargparseです。

本記事では、基礎から実践パターンまで、コピペしてすぐ使えるサンプルと図解を交えながら、コマンドライン引数を最速でマスターできることを目指して解説します。

argparseとは

argparseとは何か

Pythonのargparseは、標準ライブラリに含まれているコマンドライン引数を扱うためのライブラリです。

ユーザーがターミナルで入力した--input foo.txt-n 10といった文字列を、開発者が使いやすいPythonオブジェクトへ変換してくれます。

コマンドラインツールでは、引数の有無や値のチェック、エラーメッセージ、ヘルプメッセージの表示など、多くの処理が必要になります。

argparseはそれらをほぼ自動でやってくれる仕組みなので、わざわざ自前でパース(解析)処理を書く必要がありません。

コマンドライン引数が必要になる場面

コマンドライン引数が活躍するのは、次のような場面です。

日々の開発で書く小さなスクリプトに対して、実行時の動作を変えたいときによく使います。

例えば、画像処理なら入力ファイル名やリサイズ後のサイズ、ログ解析なら対象のログレベルや期間など、毎回変えたいパラメータは引数で指定すると便利です。

また、サーバー上でのバッチ処理やCIツールからの実行など、人が対話せずにプログラムを走らせるケースでは、コマンドライン引数がほぼ必須になります。

このような場面で、argparseを使うと「使いやすく、間違えにくい」CLIを作ることができます。

sys.argvとの違いとargparseを使うメリット

Pythonにはsys.argvという、引数をそのままリストで受け取る仕組みがあります。

これは文字列のリストが生で渡されるだけなので、次のような処理をすべて自分で書く必要があります。

  • 引数が足りないときのエラーチェック
  • "10"のような文字列を整数に変換する処理
  • --helpを実行したときに使い方を表示する処理
  • 不正なオプションが来たときのエラーメッセージ

一方でargparseを使うと、「どんな引数を受け取るのか」だけ宣言すれば、解析やエラーチェックは自動で行ってくれます

さらに、Pythonらしいラベル付きのオブジェクト(Namespace)として受け取れるので、コードの可読性も大きく向上します。

argparseの基本的な使い方

最小実行例

まずは、最小限のサンプルから見てみます。

名前を1つ受け取り、挨拶するスクリプトです。

Python
# hello.py
import argparse  # argparseモジュールをインポート

def main():
    # ArgumentParserオブジェクトを作成
    parser = argparse.ArgumentParser()
    
    # 位置引数(name)を1つ追加
    parser.add_argument("name")  # python hello.py Alice などで渡される引数
    
    # 引数を解析
    args = parser.parse_args()
    
    # 解析結果は Namespace というオブジェクトで返る
    # args.name で "Alice" のような値を取り出せる
    print(f"Hello, {args.name}!")

if __name__ == "__main__":
    main()

実行例は次の通りです。

実行結果
$ python hello.py Alice
Hello, Alice!

このように、たった数行追加するだけで、引数付きのスクリプトが完成します。

ArgumentParserの基本構造と書き方

argparseを使うときの基本構造は、どのスクリプトでもほぼ共通です。

1つの典型的なテンプレートは次のようになります。

Python
import argparse

def get_parser() -> argparse.ArgumentParser:
    """ArgumentParserを生成して返す関数"""
    parser = argparse.ArgumentParser(
        prog="mytool",                # コマンド名(省略するとファイル名)
        description="サンプルCLIツールです。",  # ヘルプの先頭に出る説明文
    )
    
    # 引数(位置引数・オプション引数)をここで定義する
    # parser.add_argument(...)

    return parser

def main():
    parser = get_parser()     # パーサーを取得
    args = parser.parse_args()  # コマンドライン引数を解析
    
    # ここから下で args を使って処理を行う
    # 例: print(args)

if __name__ == "__main__":
    main()

このように、「パーサー生成」「引数定義」「解析」「処理」の4ステップに分けて書くと、コードが整理されて読みやすくなります。

プロジェクトが大きくなっても、この構造を守っておくと保守しやすくなります。

position引数(必須引数)の定義方法

位置引数(position arguments)は、名前の前に--を付けず、順番で意味が決まる必須引数です。

具体例を見てみます。

Python
# pos_example.py
import argparse

def main():
    parser = argparse.ArgumentParser(
        description="入力ファイルを読み込んで処理し、出力ファイルに結果を書き出すサンプルです。"
    )

    # 1つ目の位置引数: input_file
    parser.add_argument("input_file", help="入力ファイルのパス")
    
    # 2つ目の位置引数: output_file
    parser.add_argument("output_file", help="出力ファイルのパス")
    
    args = parser.parse_args()

    print(f"入力: {args.input_file}")
    print(f"出力: {args.output_file}")

if __name__ == "__main__":
    main()
実行結果
$ python pos_example.py in.txt out.txt
入力: in.txt
出力: out.txt

位置引数は省略するとエラーになります。

実行結果
$ python pos_example.py in.txt
usage: pos_example.py [-h] input_file output_file
pos_example.py: error: the following arguments are required: output_file

このように、位置引数は「これがなければ動作しない必須情報」を表現するのに向いています

オプション引数(任意引数)の定義方法

オプション引数(option arguments)は、---で始まる、任意指定の引数です。

順番に依存せず、指定しなければデフォルト値が使われます。

Python
# opt_example.py
import argparse

def main():
    parser = argparse.ArgumentParser(
        description="オプション引数のサンプルです。"
    )

    # 位置引数: ファイルパス
    parser.add_argument("file", help="対象となるファイルパス")

    # オプション引数: 回数(-n または --num)
    parser.add_argument(
        "-n", "--num",
        help="処理を繰り返す回数",
        type=int,         # 受け取る値を int に変換
        default=1         # 省略されたときのデフォルト値
    )

    args = parser.parse_args()

    for i in range(args.num):
        print(f"{i+1}回目: {args.file} を処理します。")

if __name__ == "__main__":
    main()
実行結果
$ python opt_example.py data.txt
1回目: data.txt を処理します。

$ python opt_example.py data.txt --num 3
1回目: data.txt を処理します。
2回目: data.txt を処理します。
3回目: data.txt を処理します。

オプション引数は、「あれば便利だが必須ではない情報」や「動作モードを切り替えるスイッチ」を表現するのに適しています。

parse_argsで引数を取得する流れ

parser.parse_args()は、コマンドライン引数を解析してNamespaceオブジェクトにまとめて返すメソッドです。

内部で行われることは次のような流れです。

  1. OSから渡された引数リスト(sys.argv)を取得する
  2. add_argumentで定義されたルールに従って、文字列を一つずつ解析する
  3. 型指定(type=intなど)を適用して変換する
  4. 必須引数が足りない、未知の引数がある、などの異常があればエラーメッセージを表示して終了する
  5. 正常ならNamespaceオブジェクトとしてまとめて返す

返ってきたargsは、属性アクセスで簡単に値が取り出せます。

例えばargs.numargs.fileのような形です。

辞書ではなく属性でアクセスできるため、補完が効いて書きやすいのも利点です。

argparseの主な機能と便利テクニック

型指定(type)とデフォルト値(default)の設定

argparseで受け取る値は、デフォルトではすべて文字列です。

数値として扱いたい場合は、type引数で型変換を指定します。

また、defaultで省略時の値を設定できます。

Python
# type_default_example.py
import argparse

def main():
    parser = argparse.ArgumentParser(
        description="型指定とデフォルト値のサンプルです。"
    )

    parser.add_argument(
        "-n", "--num",
        type=int,          # 文字列を int に変換
        default=5,         # 省略されたときは 5
        help="処理回数(整数)。省略時は5回です。"
    )

    parser.add_argument(
        "--threshold",
        type=float,        # 浮動小数点として扱う
        default=0.8,       # 省略時のしきい値
        help="しきい値(0〜1)。省略時は0.8です。"
    )

    args = parser.parse_args()

    print(f"num の型: {type(args.num)}, 値: {args.num}")
    print(f"threshold の型: {type(args.threshold)}, 値: {args.threshold}")

if __name__ == "__main__":
    main()
実行結果
$ python type_default_example.py
num の型: <class 'int'>, 値: 5
threshold の型: <class 'float'>, 値: 0.8

$ python type_default_example.py --num 10 --threshold 0.25
num の型: <class 'int'>, 値: 10
threshold の型: <class 'float'>, 値: 0.25

型変換はバリデーションも兼ねているため、不正な値が入ると自動でエラーになります。

実行結果
$ python type_default_example.py --num abc
usage: type_default_example.py [-h] [-n NUM] [--threshold THRESHOLD]
type_default_example.py: error: argument -n/--num: invalid int value: 'abc'

必須オプション(required)と選択肢(choices)の使い方

オプション引数であっても、required=Trueを指定すると必須オプションにできます。

またchoicesを使えば、取り得る値を列挙して制限できます。

Python
# required_choices_example.py
import argparse

def main():
    parser = argparse.ArgumentParser(
        description="required と choices のサンプルです。"
    )

    # 必須オプション (configファイルは必ず指定させたい)
    parser.add_argument(
        "--config",
        required=True,    # 指定しないとエラー
        help="設定ファイルのパス(必須)。"
    )

    # choices でモードを限定
    parser.add_argument(
        "--mode",
        choices=["fast", "normal", "slow"],
        default="normal",
        help="実行モードを選択します: fast / normal / slow (デフォルト: normal)"
    )

    args = parser.parse_args()

    print(f"設定ファイル: {args.config}")
    print(f"モード: {args.mode}")

if __name__ == "__main__":
    main()

必須オプションを省略するとエラーになります。

実行結果
$ python required_choices_example.py
usage: required_choices_example.py [-h] --config CONFIG [--mode {fast,normal,slow}]
required_choices_example.py: error: the following arguments are required: --config

また、choicesにない値を渡すと自動でチェックされます。

実行結果
$ python required_choices_example.py --config app.toml --mode ultra
usage: required_choices_example.py [-h] --config CONFIG [--mode {fast,normal,slow}]
required_choices_example.py: error: argument --mode: invalid choice: 'ultra' (choose from 'fast', 'normal', 'slow')

このようにrequiredとchoicesを組み合わせることで、誤った使い方を強力に防げます

フラグ引数(store_true・store_false)の実装

store_truestore_falseは、フラグ的なオンオフ引数を扱うときに使うアクションです。

指定されたかどうかでTrue/Falseが自動でセットされます。

Python
# flag_example.py
import argparse

def main():
    parser = argparse.ArgumentParser(
        description="フラグ引数(store_true / store_false)のサンプルです。"
    )

    # --verbose が指定されたとき True、指定されなければ False
    parser.add_argument(
        "--verbose",
        action="store_true",
        help="詳細なログを表示します。"
    )

    # --no-color が指定されたとき False、指定されなければ True
    parser.add_argument(
        "--color",
        action="store_true",
        default=True,  # 初期値を True にしておき、
        help="カラー出力を有効にします(デフォルト: 有効)。"
    )
    parser.add_argument(
        "--no-color",
        dest="color",
        action="store_false",
        help="カラー出力を無効にします。"
    )

    args = parser.parse_args()

    print(f"verbose: {args.verbose}")
    print(f"color:   {args.color}")

if __name__ == "__main__":
    main()
実行結果
$ python flag_example.py
verbose: False
color:   True

$ python flag_example.py --verbose --no-color
verbose: True
color:   False

「あるかないか」で挙動を切り替えたい場合は、まずaction="store_true"を思い出すとよいです。

ヘルプメッセージ(help)と説明文(description)の整え方

argparseの大きな利点のひとつが、ヘルプメッセージを自動生成してくれることです。

ArgumentParserdescriptionadd_argumenthelpを適切に書いておくだけで、ユーザーにとって使いやすいヘルプが完成します。

Python
# help_example.py
import argparse

def main():
    parser = argparse.ArgumentParser(
        prog="imgtool",
        description="画像をリサイズするための簡易ツールです。",
        epilog="例: imgtool input.jpg --width 800 --height 600 -o output.jpg"
    )

    parser.add_argument(
        "input",
        help="入力となる画像ファイルのパス。"
    )
    parser.add_argument(
        "-o", "--output",
        help="出力先の画像ファイルパス。省略時は input と同じ場所に保存します。"
    )
    parser.add_argument(
        "--width",
        type=int,
        help="リサイズ後の幅(px)。"
    )
    parser.add_argument(
        "--height",
        type=int,
        help="リサイズ後の高さ(px)。"
    )

    args = parser.parse_args()

    print(args)

if __name__ == "__main__":
    main()

--helpを実行すると次のようになります。

実行結果
$ python help_example.py --help
usage: imgtool [-h] [-o OUTPUT] [--width WIDTH] [--height HEIGHT] input

画像をリサイズするための簡易ツールです。

positional arguments:
  input                 入力となる画像ファイルのパス。

options:
  -h, --help            show this help message and exit
  -o OUTPUT, --output OUTPUT
                        出力先の画像ファイルパス。省略時は input と同じ場所に保存します。
  --width WIDTH         リサイズ後の幅(px)。
  --height HEIGHT       リサイズ後の高さ(px)。

例: imgtool input.jpg --width 800 --height 600 -o output.jpg

descriptionには「このツールで何ができるか」、epilogには「使用例」などを書くと親切です。

ヘルプメッセージはツールの顔なので、文章をきちんと整えておくと利用者の満足度が上がります。

エラー処理と使いやすいメッセージの出し方

argparseは標準でも十分に分かりやすいエラーメッセージを出してくれますが、状況によっては独自のチェックやメッセージを追加したくなることがあります。

たとえば「widthかheightのどちらか一方は必須」といった、引数同士の関係をチェックするケースです。

Python
# error_example.py
import argparse
import sys
from pathlib import Path

def main():
    parser = argparse.ArgumentParser(
        description="簡易コピーコマンドの例です。"
    )

    parser.add_argument("src", help="コピー元ファイル")
    parser.add_argument("dst", help="コピー先ファイル")

    parser.add_argument(
        "--overwrite",
        action="store_true",
        help="コピー先が存在していても上書きします。"
    )

    args = parser.parse_args()

    src = Path(args.src)
    dst = Path(args.dst)

    # 独自のバリデーション例1: 入力ファイルの有無
    if not src.exists():
        print(f"エラー: コピー元ファイルが見つかりません: {src}", file=sys.stderr)
        sys.exit(1)

    # 独自のバリデーション例2: 上書き確認
    if dst.exists() and not args.overwrite:
        print("エラー: コピー先が既に存在します。--overwrite を付けて上書きしてください。", file=sys.stderr)
        sys.exit(1)

    print(f"{src} から {dst} へコピーします。(実処理は省略)")

if __name__ == "__main__":
    main()

このようにargparseで基本的な形式エラーを防ぎつつ、業務ロジックに応じたチェックを自前で足す形がよく使われます。

より高度にカスタマイズしたい場合は、ArgumentParserを継承してerrorメソッドをオーバーライドする方法もあります。

Python
# custom_error_parser.py
import argparse
import sys

class CustomArgumentParser(argparse.ArgumentParser):
    def error(self, message):
        # デフォルトより丁寧なメッセージに差し替える例
        self.print_usage(sys.stderr)
        print(f"\n引数エラー: {message}", file=sys.stderr)
        print("\n--help を付けて詳しい使い方を確認してください。", file=sys.stderr)
        self.exit(2)

def main():
    parser = CustomArgumentParser(description="カスタムエラーメッセージの例です。")
    parser.add_argument("--num", type=int, required=True, help="整数値を指定してください。")
    args = parser.parse_args()
    print(args)

if __name__ == "__main__":
    main()

サブコマンド(subparsers)で複数コマンドを扱う

複数の機能を1つのCLIにまとめたい場合は、サブコマンド(subparsers)を使います。

Gitのgit commitgit pushのように、コマンド名の後ろに「動詞」が続くイメージです。

Python
# subparsers_example.py
import argparse

def cmd_add(args):
    print(f"タスク追加: {args.title} (優先度: {args.priority})")

def cmd_list(args):
    print(f"タスク一覧を表示します。完了済みも表示: {args.all}")

def cmd_done(args):
    print(f"タスク完了: ID={args.id}")

def main():
    parser = argparse.ArgumentParser(
        prog="todo",
        description="シンプルなTODO管理CLIの例です。"
    )

    # サブパーサーを作成
    subparsers = parser.add_subparsers(
        title="サブコマンド",
        dest="command"  # どのサブコマンドが選択されたかをこの属性に入れる
    )
    subparsers.required = True  # Python 3.7 以降では明示的に required 指定可能

    # サブコマンド: add
    parser_add = subparsers.add_parser("add", help="新しいタスクを追加します。")
    parser_add.add_argument("title", help="タスクのタイトル")
    parser_add.add_argument(
        "-p", "--priority",
        choices=["low", "normal", "high"],
        default="normal",
        help="優先度を指定します(デフォルト: normal)。"
    )
    parser_add.set_defaults(func=cmd_add)

    # サブコマンド: list
    parser_list = subparsers.add_parser("list", help="タスク一覧を表示します。")
    parser_list.add_argument(
        "-a", "--all",
        action="store_true",
        help="完了済みタスクも含めて表示します。"
    )
    parser_list.set_defaults(func=cmd_list)

    # サブコマンド: done
    parser_done = subparsers.add_parser("done", help="タスクを完了済みにします。")
    parser_done.add_argument("id", type=int, help="完了するタスクのID")
    parser_done.set_defaults(func=cmd_done)

    args = parser.parse_args()
    # 各サブコマンドで set_defaults しておいた func を呼び出す
    args.func(args)

if __name__ == "__main__":
    main()
実行結果
$ python subparsers_example.py add "ブログを書く" --priority high
タスク追加: ブログを書く (優先度: high)

$ python subparsers_example.py list
タスク一覧を表示します。完了済みも表示: False

$ python subparsers_example.py done 3
タスク完了: ID=3

サブコマンドを使うと、1つのツールで複数の機能を整理して提供できるため、ある程度大きなCLIではほぼ必須のテクニックです。

環境変数や設定ファイルとargparseを組み合わせるコツ

実用的なツールでは、「デフォルト値は設定ファイル」「上書きは環境変数」「さらに上書きはコマンドライン」といった優先順位を付けることがよくあります。

argparseは単独では設定ファイルを読みませんが、defaultなどと組み合わせて簡単に実現できます。

以下は、環境変数MYAPP_HOSTと設定ファイルを組み合わせる例です。

Python
# config_env_example.py
import argparse
import json
import os
from pathlib import Path

def load_config(path: str | None) -> dict:
    """JSON形式の設定ファイルを読み込んで辞書で返します。"""
    if path is None:
        return {}
    p = Path(path)
    if not p.exists():
        return {}
    with p.open("r", encoding="utf-8") as f:
        return json.load(f)

def main():
    # まずは設定ファイルパスだけ先に取るためのパーサー
    pre_parser = argparse.ArgumentParser(add_help=False)
    pre_parser.add_argument(
        "--config",
        help="設定ファイル(JSON)のパス。"
    )
    # known_args_only=Trueの代わりに parse_known_args を使う
    pre_args, _ = pre_parser.parse_known_args()

    # 設定ファイルをロード
    config = load_config(pre_args.config)

    # 環境変数からのデフォルト
    env_host = os.getenv("MYAPP_HOST")

    # メインのパーサー
    parser = argparse.ArgumentParser(
        parents=[pre_parser],
        description="環境変数と設定ファイルを組み合わせる例です。"
    )

    parser.add_argument(
        "--host",
        default=config.get("host", env_host or "127.0.0.1"),
        help="接続先ホスト名。優先順位: CLI > 設定ファイル > 環境変数 > デフォルト(127.0.0.1)"
    )
    parser.add_argument(
        "--port",
        type=int,
        default=config.get("port", 8000),
        help="ポート番号。優先順位: CLI > 設定ファイル > デフォルト(8000)"
    )

    args = parser.parse_args()

    print(f"host = {args.host}")
    print(f"port = {args.port}")

if __name__ == "__main__":
    main()

このコードでは、「設定ファイル → 環境変数 → コマンドライン」の順に値を上書きしています。

自分のプロジェクトに合わせて、優先順位や読み込み元をアレンジしてください。

argparseを最速でマスターするための実践パターン

よくあるCLIツールの引数設計パターン3選

argparseを「使いこなす」には、よくある引数パターンをテンプレとして覚えるのが近道です。

ここでは代表的な3パターンを簡単に整理します。

1. ファイルフィルタ系ツール

ログやテキストをフィルタする小さなツールでは、次のような引数構成がよく使われます。

  • 位置引数: 入力ファイル
  • オプション: 出力ファイル、フィルタ条件、大小文字無視フラグなど
Python
# pattern1_file_filter.py
import argparse

def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="ログをフィルタリングするツールです。")
    parser.add_argument("input", help="入力ログファイル")
    parser.add_argument("-o", "--output", help="出力ファイル(省略時は標準出力)")
    parser.add_argument("--pattern", required=True, help="一致させるパターン文字列")
    parser.add_argument(
        "-i", "--ignore-case",
        action="store_true",
        help="大文字・小文字を区別しません。"
    )
    return parser

2. 処理バッチ系ツール

バッチ処理では、設定ファイルやドライラン、同時実行数などを持つパターンが多いです。

Python
# pattern2_batch.py
def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="定期バッチ処理のエントリーポイントです。")
    parser.add_argument("--config", required=True, help="設定ファイルパス")
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="実際には書き込みを行わず、処理内容だけを表示します。"
    )
    parser.add_argument(
        "--max-workers",
        type=int,
        default=4,
        help="同時実行するワーカー数(デフォルト: 4)。"
    )
    return parser

3. サーバー起動系ツール

WebサーバーやAPIサーバーの起動スクリプトでは、host・port・デバッグモードが定番です。

Python
# pattern3_server.py
def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="開発用Webサーバーを起動します。")
    parser.add_argument("--host", default="127.0.0.1", help="バインドするホスト(デフォルト: 127.0.0.1)")
    parser.add_argument("--port", type=int, default=8000, help="ポート番号(デフォルト: 8000)")
    parser.add_argument(
        "--debug",
        action="store_true",
        help="デバッグモードで起動します(リロード有効など)。"
    )
    return parser

これらを覚えておくと、毎回設計で迷う時間が大幅に減ります

小さなスクリプトをargparse対応にする手順

既にある「引数なしのスクリプト」をargparse対応に変えるには、次のようなステップで進めるとスムーズです。

  1. スクリプト中の「変えたい値」を関数引数にする
  2. main関数を作り、そこでargparseを使って値を受け取る
  3. mainから既存処理関数を呼び出す

例として、ファイルの行数を数えるスクリプトを変換してみます。

Python
# before.py (argparse 対応前)
from pathlib import Path

def count_lines():
    path = Path("data.txt")  # 固定のファイル名
    with path.open("r", encoding="utf-8") as f:
        print(sum(1 for _ in f))

if __name__ == "__main__":
    count_lines()

これをargparse対応にします。

Python
# after.py (argparse 対応後)
import argparse
from pathlib import Path

def count_lines(path: Path) -> None:
    """指定されたファイルの行数を数えます。"""
    with path.open("r", encoding="utf-8") as f:
        print(sum(1 for _ in f))

def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="テキストファイルの行数を数えます。")
    parser.add_argument("file", help="行数を数える対象ファイル")
    return parser

def main():
    parser = build_parser()
    args = parser.parse_args()
    count_lines(Path(args.file))

if __name__ == "__main__":
    main()

このように「処理ロジック」と「引数パース処理」を分離しておくと、後からテストを書いたり、別のUI(例えばGUI)から呼び出したりしやすくなります。

argparseコードをテンプレート化して再利用する

毎回ゼロからパーサーを書くのは面倒なので、自分なりのテンプレートを用意しておくと効率が上がります。

ここでは、比較的汎用的に使えるテンプレート例を示します。

Python
# cli_template.py
import argparse
from dataclasses import dataclass

@dataclass
class Config:
    input: str
    output: str | None
    verbose: bool

def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        description="テンプレートCLIです。inputを読み込んで、必要ならoutputに書き出します。"
    )
    parser.add_argument("input", help="入力ファイルパス")
    parser.add_argument("-o", "--output", help="出力ファイルパス(省略時は標準出力)")
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="詳細なログを表示します。"
    )
    return parser

def parse_args_to_config(parser: argparse.ArgumentParser) -> Config:
    args = parser.parse_args()
    return Config(
        input=args.input,
        output=args.output,
        verbose=args.verbose,
    )

def main():
    parser = build_parser()
    config = parse_args_to_config(parser)

    if config.verbose:
        print(f"設定: {config}")

    # ここにメインロジックを書く
    # run(config)

if __name__ == "__main__":
    main()

このテンプレートをベースに、Configクラスとbuild_parserをコピペして修正するだけで、新しいCLIを素早く作成できます。

プロジェクト全体で同じスタイルを共有しておくと、どのツールも似た操作感になり、利用者にとっても分かりやすくなります。

既存プロジェクトにargparseを導入するポイント

すでにある程度大きなプロジェクトにargparseを導入する場合は、次のポイントを意識するとスムーズです。

  1. 「エントリーポイント」を1つ決める
    まず、実行時に呼ばれるスクリプト(例えばmain.py)を特定し、そこにだけargparseを置くようにします。
  2. 業務ロジックを関数やクラスに切り出す
    main関数からは「引数をパース」→「ロジック関数を呼ぶ」だけにし、ロジック自体は既存コードを関数化して移します。
  3. 旧インターフェースとの互換性を確認する
    もし既にシェルスクリプトなどから呼ばれている場合は、引数の形式を大きく変えないようにし、必要ならラッパースクリプトを用意します。

簡単な構造の例を挙げます。

Python
# project/main.py
import argparse
from project.core import run_app  # 既存ロジックをここに集約したとする

def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description="既存プロジェクト用CLIです。")
    parser.add_argument("--config", required=True, help="設定ファイルパス")
    parser.add_argument("--debug", action="store_true", help="デバッグモードで動作します。")
    return parser

def main():
    parser = build_parser()
    args = parser.parse_args()
    # 既存ロジックは run_app に集約し、引数を渡して呼び出す
    run_app(config_path=args.config, debug=args.debug)

if __name__ == "__main__":
    main()

このように「引数パースの境界」と「ドメインロジック」を分けて設計することで、既存コードに大きな変更を加えずにargparseを導入できます。

まとめ

argparseは、Python標準ライブラリでありながら強力かつ柔軟なコマンドライン引数パーサーです。

位置引数とオプション引数の基本から、型指定、必須オプション、フラグ、サブコマンド、さらには環境変数や設定ファイルとの連携まで、一度パターンを覚えてしまえばどんなCLIツールにも応用できます。

この記事で紹介したサンプルコードやテンプレートをベースに、自分のスクリプトを少しずつargparse対応していくことで、実戦レベルのCLI設計力が身についていきます。

ぜひ手元の小さなスクリプトから試してみてください。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!