004: 「月初月締」の解答¶
難易度: ☆
方針¶
ArgumentParser に、位置引数、必須オプション、選択式オプション、真偽フラグを登録します。
--month と --tax-rate は、文字列を受け取って検査する関数を type に渡します。
検査に失敗したら ArgumentTypeError を送出すると、argparse のエラーメッセージとして扱われます。
実装¶
import argparse
def month_text(text):
if len(text) != 7 or text[4] != "-":
raise argparse.ArgumentTypeError("month must be YYYY-MM")
year_text = text[:4]
month_part = text[5:]
if not year_text.isdigit() or not month_part.isdigit():
raise argparse.ArgumentTypeError("month must be YYYY-MM")
month = int(month_part)
if not 1 <= month <= 12:
raise argparse.ArgumentTypeError("month must be between 01 and 12")
return text
def non_negative_int(text):
try:
value = int(text)
except ValueError as exc:
raise argparse.ArgumentTypeError("expected int") from exc
if value < 0:
raise argparse.ArgumentTypeError("expected non-negative int")
return value
def build_sales_parser():
parser = argparse.ArgumentParser(prog="sales-report")
parser.add_argument("csv_path")
parser.add_argument("--month", required=True, type=month_text)
parser.add_argument("--format", choices=["table", "json"], default="table")
parser.add_argument("--tax-rate", type=non_negative_int, default=10)
parser.add_argument("--include-zero", action="store_true")
return parser
def parse_sales_args(args):
namespace = build_sales_parser().parse_args(args)
return vars(namespace)
確認¶
assert parse_sales_args(["sales.csv", "--month", "2026-06"]) == {
"csv_path": "sales.csv",
"month": "2026-06",
"format": "table",
"tax_rate": 10,
"include_zero": False,
}
assert parse_sales_args([
"sales.csv",
"--month", "2026-06",
"--format", "json",
"--tax-rate", "8",
"--include-zero",
]) == {
"csv_path": "sales.csv",
"month": "2026-06",
"format": "json",
"tax_rate": 8,
"include_zero": True,
}
発展¶
並び順を増やす場合は、parser.add_argument("--sort", choices=[...]) を追加します。
ここで返した設定辞書を、CSV集計の関数へ渡せば、CLI部分と集計部分を分けて実装できます。