Read command-line arguments with argparse
A script run from a terminal gets its options as words. argparse turns them into named, typed values, fills in defaults, and stops with a clear message when the input is wrong.
- Add a positional argument, an option with a default, and an option with
type=int - Use
choicesandaction="store_true"for fixed values and on/off flags - Explain what happens on bad input: a usage message and exit status 2
A shop's finance team runs python export_invoices.py invoices.csv --country France --limit 5 every morning. Python hands the script those words as a list of text: ["invoices.csv", "--country", "France", "--limit", "5"]. Picking that list apart by position is fragile: options can come in any order, some are optional, and "5" is text, not a number.
argparse (standard library) does the work. You describe each argument once with add_argument, then parse_args reads the list and gives back an object with one attribute per argument. A name without dashes ("path") is a positional argument and is required. A name with two dashes ("--limit") is an option: it may be left out, and then it gets its default. type=int converts the text and rejects anything that isn't a whole number.
In a terminal you call parser.parse_args() with no list, and it reads the words typed after the script name. Passing the list yourself, as below, runs the very same parsing, which is also how you test a command-line script.
Run each example to see what it prints. Running examples doesn't count toward progress.
import argparse parser = argparse.ArgumentParser(prog="export_invoices") parser.add_argument("path") parser.add_argument("--country", default="United Kingdom") parser.add_argument("--limit", type=int, default=10) args = parser.parse_args(["invoices.csv", "--limit", "5"]) print(args.path) print(args.country) print(args.limit, type(args.limit))
When the input breaks the rules, argparse doesn't return at all. It writes a usage line and the reason to the error stream and ends the program with exit status 2, the convention for "you called me wrong". It does this by raising SystemExit, which is how any Python program stops early.
import argparse parser = argparse.ArgumentParser(prog="export_invoices") parser.add_argument("path") parser.add_argument("--limit", type=int, default=10) args = parser.parse_args(["invoices.csv", "--limit", "five"]) print("exporting", args.limit, "invoices")
Two more kinds of argument cover most scripts. choices=[...] accepts only the listed values. action="store_true" makes an on/off flag: it takes no value, and is True when present and False when absent. A dash in an option name becomes an underscore in the attribute: --dry-run is read as args.dry_run.
Keeping the parser inside a function that takes the argument list makes it easy to call with several lists. The built-in vars(args) turns the parsed result into an ordinary dictionary.
import argparse def read_options(argv): parser = argparse.ArgumentParser(prog="export_invoices") parser.add_argument("path") parser.add_argument("--format", choices=["csv", "json"], default="csv") parser.add_argument("--dry-run", action="store_true") return vars(parser.parse_args(argv)) print(read_options(["march.csv"])) print(read_options(["march.csv", "--format", "json", "--dry-run"])) print(read_options(["--dry-run", "april.csv"]))
When to use it: any script someone runs with options. argparse also writes --help for free from the same descriptions.
Mistakes to avoid: forgetting type=int, so args.limit * 2 repeats text instead of doubling a number; writing args.dry-run (Python reads that as args.dry - run); and checking a rule by printing a message and carrying on. For a rule that type and choices can't express, such as *the amount must be positive*, call parser.error("amount must be positive") after parsing: it prints the usage and your message and exits with status 2, exactly like argparse's own errors.
add_argument("path")is a required positional;add_argument("--name", default=...)is an option.type=converts and validates,choices=limits the values,action="store_true"makes a flag; dashes become underscores.- Bad input ends the program with a usage message and status 2; use
parser.errorfor your own rules. - Next: finding the files a script should work on, with pathlib.