Building Command-Line Programs with argparse
Define positional arguments, options, flags, validation, help, and subcommands with Python’s argparse module.
Intermediate
A command-line program receives arguments from the environment that launches it. Python’s argparse module turns those tokens into named values, checks them, and generates a useful help page. The lesson focuses on defining a clear interface and validating input before your program acts on it.
Start with an argument parser
Create an ArgumentParser, describe the program, and register each argument with add_argument(). Positional arguments are identified by their place in the command; optional arguments are named with flags such as --greeting. argparse adds -h and --help automatically and reports missing or unknown arguments without requiring hand-written parsing code.
Output
Ready to run.
Convert and constrain input
Command-line tokens begin as strings. Supply type=int or another deliberate converter when the program needs a different type. Use choices for a small permitted set of values, and provide help text that describes what a user should enter. Invalid values are rejected by the parser before your application logic runs.
Output
Ready to run.
Quick check
Why use type=int for an argument that represents a quantity?
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("count", type=int)
args = parser.parse_args(["6"])
assert args.count == 6 and isinstance(args.count, int)
print(args.count + 1)
Add flags and defaults
An option such as --verbose often represents a yes/no choice rather than a value. Use action="store_true" for a flag that defaults to False and becomes True when present. Optional values that need no explicit command-line token should have deliberate defaults, so later code does not need to guess what None means.
Output
Ready to run.
Quick check
What value does a store_true flag have when the user does not supply it?
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--dry-run", action="store_true")
args = parser.parse_args([])
print(args.dry_run)
Express options that cannot be combined
When two modes should not be active at the same time, place them in add_mutually_exclusive_group(). For example, --json and --plain can select alternative output styles. The parser then explains the conflict automatically if a user supplies both. This is clearer than accepting contradictory flags and resolving them later in application code.
Output
Ready to run.
Quick check
What does a mutually exclusive argument group do?
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("--quiet", action="store_true")
group.add_argument("--verbose", action="store_true")
args = parser.parse_args(["--quiet"])
print(args.quiet, args.verbose)
Build subcommands for distinct actions
Use add_subparsers() when a program offers named actions such as add, list, or remove. Each subcommand gets its own arguments and help text. Setting dest stores the selected command name; required=True makes the user choose a valid subcommand. Subcommands keep a growing command-line interface organized without manually examining the first token.
Output
Ready to run.
Quick check
Why use subparsers for a CLI with add and list actions?
import argparse
parser = argparse.ArgumentParser()
commands = parser.add_subparsers(dest="command", required=True)
commands.add_parser("show")
commands.add_parser("clear")
args = parser.parse_args(["show"])
print(args.command)
Keep parsing separate from program work
A useful design puts parser construction in build_parser() and application behavior in main(argv=None). Passing an explicit argument list makes the program easy to test; leaving argv as None lets parse_args() read the real command line when the program runs. Treat all user-supplied arguments as input: constrain choices, convert types deliberately, and do not evaluate arbitrary strings as Python code. Shell-command execution and process control are separate topics in the curriculum.
Output
Ready to run.
Quick check
Why allow main(argv=None) to receive an explicit list during tests?
import argparse
def parse_count(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument("count", type=int)
return parser.parse_args(argv).count
print(parse_count(["8"]))
The current Python 3.15 reference documents additional ArgumentParser help features: color output and suggest_on_error were added in Python 3.14, and the suggest_on_error default changed in Python 3.15. This lesson avoids those version-specific settings because the available local interpreter is Python 3.13.5; the examples use the stable parser APIs that were executed locally.
Design note: argparse is the recommended standard-library starting point for ordinary command-line interfaces. This lesson does not claim to cover every CLI concern: environment configuration, standard streams, process exit statuses, direct sys.argv use, subprocess security, and Python interpreter flags remain distinct checklist items.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.