Lesson 14 · Python standard library deep dive
Python argparse Explained: Build Real CLI Tools | Standard Library #14
Video fourteen of the twenty-five-part series: argparse, for building real, professional command-line interfaces. Positional and optional arguments, types,…
- CoursePython standard library deep dive
- Lesson14 of 24
- Video16 min
- FormatJupyter notebook · 11 code cells
- Data3 datasets
What you'll learn
Datasets used in this lesson
Save these next to the notebook. In Google Colab, upload them with the 📁 icon on the left first.
📓 Full notebook
Download .ipynbPython Standard Library Deep-Dive, Video 14: argparse#
- Video fourteen of the twenty-five-part series: argparse, for building real, professional command-line interfaces.
- Positional and optional arguments, types, flags, choices, multiple values, subcommands, and auto-generated help.
- A quick note: every example here calls parse_args with an explicit list, exactly how a real CLI script would be unit tested, so these cells run identically here and in a genuine terminal.
- Let's get into it.
Part 1: What argparse Offers#
import argparse
parser = argparse.ArgumentParser(description='A demo command-line tool')
print(type(parser))
Part 2: Positional Arguments#
parser = argparse.ArgumentParser()
parser.add_argument('filename')
args = parser.parse_args(['report.csv'])
print(args.filename)
print(args)
parser = argparse.ArgumentParser()
parser.add_argument('filename')
try:
parser.parse_args([])
except SystemExit as e:
print(f'Caught: argparse genuinely called sys.exit with code {e.code}')
Part 3: Optional Arguments and Flags#
parser = argparse.ArgumentParser()
parser.add_argument('filename')
parser.add_argument('-v', '--verbose', help='enable verbose output')
args = parser.parse_args(['report.csv', '--verbose', 'yes'])
print(args.filename, args.verbose)
args2 = parser.parse_args(['report.csv'])
print(args2.verbose)
Part 4: Types and Defaults#
parser = argparse.ArgumentParser()
parser.add_argument('--count', type=int, default=1)
parser.add_argument('--rate', type=float, default=1.0)
args = parser.parse_args(['--count', '5', '--rate', '2.5'])
print(args.count, type(args.count))
print(args.rate, type(args.rate))
args2 = parser.parse_args([])
print(args2.count, args2.rate)
Part 5: Boolean Flags with action='store_true'#
parser = argparse.ArgumentParser()
parser.add_argument('--force', action='store_true')
parser.add_argument('--dry-run', action='store_true')
args = parser.parse_args(['--force'])
print(args.force, args.dry_run)
args2 = parser.parse_args([])
print(args2.force, args2.dry_run)
Part 6: choices and Validation#
parser = argparse.ArgumentParser()
parser.add_argument('--format', choices=['csv', 'json', 'xml'], default='csv')
args = parser.parse_args(['--format', 'json'])
print(args.format)
try:
parser.parse_args(['--format', 'yaml'])
except SystemExit:
print('Caught: an invalid choice genuinely got rejected automatically')
Part 7: nargs - Multiple Values#
parser = argparse.ArgumentParser()
parser.add_argument('--files', nargs='+')
args = parser.parse_args(['--files', 'a.txt', 'b.txt', 'c.txt'])
print(args.files)
print(type(args.files))
parser2 = argparse.ArgumentParser()
parser2.add_argument('--tags', nargs='*', default=[])
print(parser2.parse_args([]).tags)
print(parser2.parse_args(['--tags', 'x', 'y']).tags)
Part 8: Subcommands#
parser = argparse.ArgumentParser(prog='mytool')
subparsers = parser.add_subparsers(dest='command')
add_parser = subparsers.add_parser('add')
add_parser.add_argument('--value', type=int, required=True)
remove_parser = subparsers.add_parser('remove')
remove_parser.add_argument('--id', type=int, required=True)
args1 = parser.parse_args(['add', '--value', '42'])
print(args1.command, args1.value)
args2 = parser.parse_args(['remove', '--id', '7'])
print(args2.command, args2.id)
Part 9: Help Text and Argument Groups#
parser = argparse.ArgumentParser(
prog='analyzer',
description='Analyze a dataset and produce a report'
)
parser.add_argument('input_file', help='path to the input data file')
output_group = parser.add_argument_group('output options')
output_group.add_argument('--output', help='where to write the report')
output_group.add_argument('--format', choices=['pdf', 'html'], default='pdf')
help_text = parser.format_help()
print('input_file' in help_text)
print('output options' in help_text)
print('Analyze a dataset' in help_text)
Part 10: Common Patterns#
def build_parser():
parser = argparse.ArgumentParser(description='Process a data file')
parser.add_argument('input_file')
parser.add_argument('--output', default='output.csv')
parser.add_argument('--verbose', action='store_true')
parser.add_argument('--format', choices=['csv', 'json'], default='csv')
return parser
def main(argv):
parser = build_parser()
args = parser.parse_args(argv)
if args.verbose:
print(f'Processing {args.input_file} -> {args.output} as {args.format}')
return 0
exit_code = main(['data.csv', '--verbose', '--format', 'json'])
print(exit_code)
Wrap-Up: What You Learned#
- argparse parses, validates, and type-converts command-line arguments declaratively.
- Positional arguments are required by position; optional arguments start with dashes and default to None.
- type converts raw strings automatically; default supplies a fallback when an argument is omitted.
- action='store_true' builds a genuine on-off flag with no separate value.
- choices restricts an argument to a fixed valid set, rejecting anything else automatically.
- nargs controls how many values an argument consumes: plus, star, or question mark.
- add_subparsers builds independent sub-commands, each with its own arguments, like git's own commands.
- Help text and argument groups are auto-generated from descriptions and help strings.
- A real pattern: a testable build_parser plus main(argv) function, never touching sys.argv directly in tests.
- That wraps up argparse. Next up: pickle and shelve, for object serialization and simple persistence.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



