These two options cover most validation and multi-value needs without custom code.
choices= limits an argument to a fixed set: choices=["json", "csv"]. Invalid values get a clear error listing the options, and help shows them. Checking happens after type conversion, so type=int, choices=range(1, 6) works.
nargs= controls how many command-line words an argument consumes:
- an integer
N: exactly N values, as a list (nargs=2for--size W H), "?": zero or one. An option given without a value takesconst; absent, it takesdefault,"*": zero or more, as a list,"+": one or more, error if none,argparse.REMAINDER: everything that's left (rarely needed; prefer--separation).
A common pattern is add_argument("files", nargs="+", type=Path) for "one or more files".
The ? + const combination gives three-state options:
p.add_argument("--log", nargs="?", const="app.log", default=None)
# absent -> None; --log -> 'app.log'; --log x.log -> 'x.log'Be careful with several variable-length positionals in one parser: argparse matches greedily, so the split between them may not be what users expect.
Example
import argparse
from pathlib import Path
p = argparse.ArgumentParser(prog="conv")
p.add_argument("files", nargs="+", type=Path)
p.add_argument("--to", choices=["json", "csv"], default="json")
p.add_argument("--size", nargs=2, type=int, metavar=("W", "H"))
p.add_argument("--log", nargs="?", const="app.log")
a = p.parse_args(["a.txt", "b.txt", "--size", "640", "480", "--log"])
print([f.name for f in a.files], a.to, a.size, a.log)
# ['a.txt', 'b.txt'] json [640, 480] app.log
print(p.parse_args(["x", "--log", "debug.log"]).log) # debug.log
try:
p.parse_args(["x", "--to", "xml"])
except SystemExit:
pass
# conv: error: argument --to: invalid choice: 'xml' (choose from 'json', 'csv')Remember
- choices restricts values and is checked after type conversion
- nargs: N, '?', '*', '+' control how many values are consumed
- nargs='?' with const gives absent / flag / value behaviour
Watch out for
- Using nargs='*' for a required list; use '+' so an empty list is an error.