Lab 11: CLI Tools — argparse & rich

Objective

Build polished command-line tools using argparse for argument parsing and rich for beautiful terminal output: progress bars, tables, syntax highlighting, and logging.

Time

30 minutes

Prerequisites

  • Lab 08 (SQLite), Lab 09 (FastAPI)

Tools

  • Docker image: zchencow/innozverse-python:latest


Lab Instructions

Step 1: argparse — Argument Parsing

docker run --rm zchencow/innozverse-python:latest python3 -c "
import argparse
import sys

# Build a parser programmatically
parser = argparse.ArgumentParser(
    prog='storecli',
    description='innoZverse Store CLI — Manage your product catalog',
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog='Examples:\n  storecli list --category Laptop\n  storecli create --name \"Surface Pro\" --price 864'
)

subparsers = parser.add_subparsers(dest='command', required=True)

# List subcommand
list_parser = subparsers.add_parser('list', help='List products')
list_parser.add_argument('--category', '-c', help='Filter by category')
list_parser.add_argument('--sort', choices=['name', 'price', 'stock'], default='name')
list_parser.add_argument('--order', choices=['asc', 'desc'], default='asc')
list_parser.add_argument('--limit', type=int, default=20)
list_parser.add_argument('--format', choices=['table', 'json', 'csv'], default='table')
list_parser.add_argument('--verbose', '-v', action='store_true')

# Create subcommand
create_parser = subparsers.add_parser('create', help='Create a product')
create_parser.add_argument('--name', '-n', required=True)
create_parser.add_argument('--price', '-p', type=float, required=True)
create_parser.add_argument('--stock', '-s', type=int, default=0)
create_parser.add_argument('--category', '-c', default='General')

# Get subcommand
get_parser = subparsers.add_parser('get', help='Get product by ID')
get_parser.add_argument('id', type=int, help='Product ID')

# Delete subcommand
del_parser = subparsers.add_parser('delete', help='Delete a product')
del_parser.add_argument('id', type=int, help='Product ID')
del_parser.add_argument('--force', '-f', action='store_true', help='Skip confirmation')

# Stats subcommand
subparsers.add_parser('stats', help='Show inventory statistics')

# Parse test args (normally sys.argv[1:])
def run(args_str: str):
    args = parser.parse_args(args_str.split())
    print(f'Command: {args.command}')
    print(f'Args: {vars(args)}')
    print()

run('list --category Laptop --sort price --order desc')
run('create --name \"Surface Pro\" --price 864.0 --stock 15 --category Laptop')
run('get 1')
run('stats')
"

💡 subparsers let you build Git-style CLIs (git commit, git push) where each subcommand has its own arguments. action='store_true' makes a flag that sets the value to True when present. type=int auto-converts the string argument to an integer.

📸 Verified Output:


Step 2: rich — Beautiful Terminal Output

📸 Verified Output:


Steps 3–8: Logging, Config files, stdin/stdout piping, Interactive prompts, Error formatting, Capstone

📸 Verified Output:


Summary

Tool
Purpose
Key classes

argparse

Parse CLI arguments

ArgumentParser, add_subparsers

rich.console

Styled output

Console, print()

rich.table

Terminal tables

Table, Column

rich.panel

Bordered panels

Panel.fit()

rich.progress

Progress bars

Progress, BarColumn

rich.logging

Pretty log output

RichHandler

sys.stdout

Pipe-friendly output

print() → stdout

Further Reading

Last updated