The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Create a parser | parser = argparse.ArgumentParser(prog='tool', description='Process records') | View examples |
| Add a positional | parser.add_argument('input', help='input path') | View examples |
| Add an option | parser.add_argument('-o', '--output', default='-') | View examples |
| Parse an explicit list | args = parser.parse_args(['input.csv', '--output', 'result.json']) | View examples |
| Convert a value | parser.add_argument('--limit', type=int, default=100) | View examples |
| Restrict choices | parser.add_argument('--format', choices=('json', 'csv')) | View examples |
| Add positive and negative flags | parser.add_argument('--cache', action=argparse.BooleanOptionalAction, default=True) | View examples |
| Count repeated flags | parser.add_argument('-v', '--verbose', action='count', default=0) | View examples |
| Require one or more values | parser.add_argument('files', nargs='+') | View examples |
| Append repeated option values | parser.add_argument('--tag', action='append', default=[]) | View examples |
| Omit an absent attribute | parser.add_argument('--token', default=argparse.SUPPRESS) | View examples |
| Set parser-wide defaults | parser.set_defaults(timeout=30, handler=run) | View examples |
| Create required subcommands | commands = parser.add_subparsers(dest='command', required=True) | View examples |
| Declare a subcommand | build = commands.add_parser('build', help='build artifacts') | View examples |
| Dispatch to a handler | result = args.handler(args) | View examples |
| Validate with a type function | parser.add_argument('--port', type=parse_port) | View examples |
| Make options mutually exclusive | mode = parser.add_mutually_exclusive_group(required=True) | View examples |
| Retain unknown tokens | args, remaining = parser.parse_known_args(argv) | View examples |
| Populate an existing namespace | args = parser.parse_args(argv, namespace=argparse.Namespace(source='config')) | View examples |
| Render plain help | parser = argparse.ArgumentParser(prog='tool', color=False) | View examples |
| Catch conversion errors | parser = argparse.ArgumentParser(exit_on_error=False) | View examples |
| Generate help text | help_text = parser.format_help() | View examples |
argparse translates command-line strings into typed application inputs while generating usage and help text from the same declaration. A durable CLI keeps parsing separate from execution, makes defaults and mutually exclusive choices visible, and tests explicit argument lists rather than mutating global process state. Treat names, exit codes, and diagnostics as a public interface: scripts and people may rely on them long after the first release.
Step by step
Detailed examples
Parse strings at the boundary and keep execution separate
ArgumentParser derives usage and help from declarations. Positionals are identified by order; options are identified by prefixed names and normally derive their destination from the long name. parse_args() reads sys.argv[1:] when no list is provided, but application code is easier to test when a build_parser function returns the parser and main accepts an optional argv list. Values remain strings unless type or an action converts them.
import argparse
def build_parser():
parser = argparse.ArgumentParser(prog='convert', description='Convert a document')
parser.add_argument('input', help='input path')
parser.add_argument('-o', '--output', default='-', help='output path')
return parser
args = build_parser().parse_args(['report.txt', '--output', 'report.json'])
print(args.input)
print(args.output) report.txt
report.jsonUse actions for CLI syntax and validate semantics separately
type converts one token and choices constrains the converted result. Actions such as store_true, count, append, and BooleanOptionalAction describe how occurrences update the namespace. BooleanOptionalAction has generated --foo and --no-foo forms since Python 3.9. Avoid type=bool because any nonempty string is truthy, and avoid doing network or irreversible work in a converter—parsing can invoke it before other arguments are known to be valid.
import argparse
parser = argparse.ArgumentParser(prog='export')
parser.add_argument('--limit', type=int, default=100)
parser.add_argument('--format', choices=('json', 'csv'), default='json')
parser.add_argument('--cache', action=argparse.BooleanOptionalAction, default=True)
parser.add_argument('-v', '--verbose', action='count', default=0)
args = parser.parse_args(['--limit', '25', '--format', 'csv', '--no-cache', '-vv'])
print(args.limit, type(args.limit).__name__)
print(args.format, args.cache, args.verbose) 25 int
csv False 2Model cardinality and distinguish absent from defaulted
nargs controls how many tokens one declaration consumes: '?' accepts zero or one, '*' zero or more, and '+' one or more. append records repeated option occurrences. Mutable defaults are reused by repeated parse_args calls on the same parser, so application code should avoid mutating a parsed default list. argparse.SUPPRESS omits an absent destination entirely, which is useful when command-line values should selectively override a configuration mapping rather than replace it with None.
import argparse
parser = argparse.ArgumentParser(prog='upload')
parser.add_argument('files', nargs='+')
parser.add_argument('--tag', action='append', default=[])
parser.add_argument('--token', default=argparse.SUPPRESS)
args = parser.parse_args(['one.txt', 'two.txt', '--tag', 'docs', '--tag', 'public'])
print(args.files)
print(args.tag)
print(hasattr(args, 'token')) ['one.txt', 'two.txt']
['docs', 'public']
FalseGive each subcommand an isolated contract and handler
add_subparsers creates command-specific child parsers. Set required=True, available since Python 3.7, when running without a command is invalid. Each child can attach a handler with set_defaults, avoiding a central conditional that must know every command. Only attributes declared for the selected parser are guaranteed to exist, so handlers should consume their own namespace contract rather than assume sibling options are present.
import argparse
def greet(args):
return f'hello {args.name}'
def add(args):
return str(sum(args.values))
parser = argparse.ArgumentParser(prog='demo')
commands = parser.add_subparsers(dest='command', required=True)
greet_parser = commands.add_parser('greet')
greet_parser.add_argument('name')
greet_parser.set_defaults(handler=greet)
add_parser = commands.add_parser('add')
add_parser.add_argument('values', nargs='+', type=int)
add_parser.set_defaults(handler=add)
for argv in (['greet', 'Ada'], ['add', '4', '6']):
args = parser.parse_args(argv)
print(args.command, args.handler(args)) greet hello Ada
add 10Report local input mistakes during parsing
A type callable can raise ArgumentTypeError to produce a concise argument-specific diagnostic. Use it for deterministic validation of one token, then perform cross-field, filesystem, network, and business validation after parsing. A mutually exclusive group prevents conflicting syntax; required=True means exactly one member must appear. Groups cannot express every dependency, and nesting argument or mutually exclusive groups is deprecated, so complex rules belong in ordinary Python with focused tests.
import argparse
def parse_port(value):
port = int(value)
if not 1 <= port <= 65535:
raise argparse.ArgumentTypeError('port must be between 1 and 65535')
return port
parser = argparse.ArgumentParser(prog='serve')
parser.add_argument('--port', type=parse_port, default=8000)
mode = parser.add_mutually_exclusive_group(required=True)
mode.add_argument('--http', action='store_const', const='http', dest='mode')
mode.add_argument('--https', action='store_const', const='https', dest='mode')
args = parser.parse_args(['--port', '8443', '--https'])
print(args.mode)
print(args.port) https
8443Pass unknown arguments only across an intentional boundary
parse_known_args returns recognized values plus unmatched tokens, which is useful for wrappers and staged parsers. Because prefix matching can consume an apparent unknown as an abbreviation of a known long option, set allow_abbrev=False when forwarding must be exact. Never silently discard the remaining list. Passing namespace populates an existing object: an existing attribute survives when its argument is absent, while an explicit command-line value replaces it. Define and test configuration precedence rather than relying on an accidental merge order.
import argparse
parser = argparse.ArgumentParser(prog='wrapper', allow_abbrev=False)
parser.add_argument('--profile')
base = argparse.Namespace(source='config')
args, remaining = parser.parse_known_args(
['--profile', 'fast', '--worker-count', '4'],
namespace=base,
)
print(args.profile, args.source)
print(remaining) fast config
['--worker-count', '4']Keep diagnostics stable without assuming every error is catchable
By default argparse prints a diagnostic and exits with status 2 for invalid input; --help exits with status 0. exit_on_error=False, introduced in Python 3.9, makes some errors such as type and choice failures raise ArgumentError, but it does not convert every exit path, so library code may still need a carefully tested parser subclass. Python 3.14 added suggest_on_error and colored help; color depends on the terminal and environment, so set color=False when capturing stable help on 3.14+. format_help returns text without exiting and works across supported versions.
import argparse
parser = argparse.ArgumentParser(prog='scale', exit_on_error=False)
parser.add_argument('--factor', type=int, required=True, help='integer multiplier')
try:
parser.parse_args(['--factor', 'many'])
except argparse.ArgumentError as error:
print(error.argument_name)
print('invalid int' in str(error))
help_text = parser.format_help()
print(help_text.startswith('usage: scale'))
print('integer multiplier' in help_text) --factor
True
True
TrueLocal code tester
Design and exercise a subcommand parser
Add options to a small task CLI and test explicit argument lists without touching the notebook process arguments.
Press Run to load Python locally.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- Python Software Foundationargparse — Parser for command-line options, arguments and subcommandsdocs.python.org
- Python Software FoundationArgparse Tutorialdocs.python.org
- Python Software FoundationPEP 389 — argparse: New Command Line Parsing Modulepeps.python.org
- Python Software FoundationPython command-line and environment documentationdocs.python.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



