Building Python CLI Tools with argparse and Subcommands
I built Unix-friendly Python CLIs with argparse subcommands, validated arguments, and meaningful exit codes. Following CLI conventions made the tools composable in shell pipelines and reliable in CI, where exit status drives control flow.
Objective & Context
A good CLI is predictable: clear help, validated input, and a non-zero exit on failure. This lab uses argparse subparsers and returns proper exit codes so scripts behave correctly under set -e and in automated pipelines.
Environment & Prerequisites
- Python 3.11 with argparse (standard library).
- A shell to test piping and exit codes.
- A task with at least two subcommands.
flowchart LR
CLI[argv] --> P[argparse parse]
P --> S{subcommand}
S -->|scan| Sc[run scan]
S -->|report| Rp[run report]
Sc --> E[exit code]
Rp --> E
Step-by-Step Execution
1. Define subcommands
import argparse, sys
p = argparse.ArgumentParser(prog="tyfctl")
sub = p.add_subparsers(dest="cmd", required=True)
sub.add_parser("scan").add_argument("target")
args = p.parse_args()
2. Return a meaningful exit code
python tyfctl.py scan 192.168.20.0/24; echo "exit=$?"3. Confirm generated help
python tyfctl.py --helpusage: tyfctl [-h] {scan,report} ...
exit=0
Validation & Testing
Run each subcommand with valid and invalid arguments and check the exit code in the shell. Pass criteria: usage errors exit non-zero with help, success exits 0, and the tool reads stdin/writes stdout cleanly for piping.
Advanced: Troubleshooting
- Always exits 0: call
sys.exit(code)explicitly on failure paths. - Broken pipes: handle
BrokenPipeErrorwhen output is piped to head. - Unclear errors: let argparse handle validation; it prints usage and exits 2.
Key Results
- Shipped CLIs with subcommands and auto-generated help.
- Returned correct exit codes for clean CI/pipeline integration.
- Validated arguments declaratively via argparse.
- Made tools composable through stdin/stdout conventions.