python 42 lines · 6 steps

Building a subcommand CLI with argparse

How argparse subparsers dispatch to per-command handler functions in a Python tool.

Explained by highlit
1import argparse
2import sys
3from pathlib import Path
4 
5 
6def cmd_init(args):
7 target = Path(args.directory)
8 target.mkdir(parents=True, exist_ok=True)
9 (target / "config.toml").write_text(f"name = \"{args.name}\"\n")
10 print(f"Initialized project in {target}")
11 
12 
13def cmd_build(args):
14 src = Path(args.source)
15 if not src.exists():
16 sys.exit(f"error: source {src} does not exist")
17 flags = ["--release"] if args.release else []
18 print(f"Building {src} {' '.join(flags)}".rstrip())
19 
20 
21def build_parser():
22 parser = argparse.ArgumentParser(prog="proj", description="Project tool")
23 parser.add_argument("-v", "--verbose", action="count", default=0)
24 sub = parser.add_subparsers(dest="command", required=True)
25 
26 p_init = sub.add_parser("init", help="create a new project")
27 p_init.add_argument("directory")
28 p_init.add_argument("-n", "--name", default="untitled")
29 p_init.set_defaults(func=cmd_init)
30 
31 p_build = sub.add_parser("build", help="build the project")
32 p_build.add_argument("source", nargs="?", default="src")
33 p_build.add_argument("--release", action="store_true")
34 p_build.set_defaults(func=cmd_build)
35 
36 return parser
37 
38 
39def main(argv=None):
40 parser = build_parser()
41 args = parser.parse_args(argv)
42 args.func(args)
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Subparsers let one program expose distinct commands, each with its own arguments and defaults.
  2. 2Attaching a handler via set_defaults(func=...) turns argument parsing into clean command dispatch.
  3. 3Keeping parsing in build_parser and logic in cmd_* functions makes the CLI easy to test and extend.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a subcommand CLI with argparse — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code