← Back to Python series
🛠
Practice Projects · ★★★★
argparse · subcommands · Config · Entry point

Project 13 — Argparse CLI Tool

Build a professional command-line tool with argparse subcommands, a config file, logging, and a pip-installable entry point.

argparseCLIsubcommandsconfigentry_point
Duration
2.5 hours
Level
📊 Advanced Applied
Prerequisite
🎯 Advanced Week 9
OUTCOME
A pip-installable CLI tool with subcommands and config file support

What you'll learn

  • 1Implement subcommands with add_subparsers
  • 2Read config from ~/.toolrc (JSON or TOML)
  • 3Add --verbose and --quiet logging levels
  • 4Write a setup.py / pyproject.toml entry point

Usage

bash
# Install
pip install -e .

# Usage
mytool --help
mytool init [--name NAME]
mytool run <file> [--dry-run] [--output FILE]
mytool config set <key> <value>
mytool config get <key>

Config File

json
// ~/.toolrc
{
  "output_dir": "./output",
  "log_level": "INFO",
  "max_workers": 4
}

Common Mistakes (FAQ)

Q. How do I structure subcommands like `git commit`?

sub = parser.add_subparsers(dest='command'); then sub.add_parser('init'), sub.add_parser('run'), each with its own add_argument. Dispatch on args.command. Set required=True (Py3.7+) so running with no subcommand shows help instead of silently doing nothing.

Q. My numeric argument arrives as a string.

argparse keeps everything as str unless you say otherwise: add_argument('--workers', type=int). Same for float. Without type=, '4' + 1 raises a TypeError.

Q. How do I make a boolean flag like --dry-run?

Use action='store_true' (and 'store_false' for the inverse). The flag then takes no value: --dry-run sets args.dry_run = True, absent = False.

Q. After `pip install -e .` the `mytool` command isn't found.

Define a console_scripts entry point in pyproject.toml ([project.scripts] mytool = 'pkg.cli:main'), reinstall with pip install -e ., and reopen the shell so PATH picks up the new script.

Q. Reading ~/.toolrc fails the first time.

Expand the home dir with Path.home() / '.toolrc' (not a literal '~'), and handle the missing-file case: if it doesn't exist, fall back to defaults instead of crashing.

📝 Exercises

Try them yourself first, then open the solution to compare.

Exercise 1

Build the CLI tool

Goal: Implement a CLI with at least 3 subcommands, config file, and entry point.

Requirements
  • 3+ subcommands with argparse
  • Config read/write with ~/.toolrc
  • --verbose/-v flag
  • pip-installable entry point
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗