Python CLI — Command-Line Interface Tools

Python AdvancedCLIFree Lesson

Advertisement

Python CLI — Command-Line Interface Tools

CLIs make your Python scripts reusable and automatable from the terminal. A well-designed CLI is essential for DevOps tools, data pipelines, and developer utilities.

Learning Objectives

  • Build CLIs with argparse (standard library)
  • Create rich CLIs with click (decorators)
  • Build type-safe CLIs with typer
  • Add subcommands, options, and validation

argparse — Standard Library

import argparse

# Create parser
parser = argparse.ArgumentParser(
    description="Process files and generate reports",
    epilog="Example: python process.py data.csv -o report.html -v"
)

# Positional arguments
parser.add_argument("input", help="Input file path")

# Optional arguments
parser.add_argument("-o", "--output", default="output.txt",
                    help="Output file (default: output.txt)")
parser.add_argument("-v", "--verbose", action="store_true",
                    help="Enable verbose output")
parser.add_argument("-n", "--count", type=int, default=1,
                    help="Number of times to repeat")
parser.add_argument("--format", choices=["csv", "json", "html"],
                    default="csv", help="Output format")

# Parse and use
args = parser.parse_args()
print(f"Input: {args.input}")
print(f"Output: {args.output}")
print(f"Verbose: {args.verbose}")

click — Decorator-Based CLI

import click

@click.command()
@click.argument("filename")
@click.option("--count", "-n", default=1, help="Number of times to repeat")
@click.option("--verbose", "-v", is_flag=True, help="Verbose output")
@click.option("--format", type=click.Choice(["csv", "json", "html"]), default="csv")
def process(filename, count, verbose, format):
    """Process a file and generate output."""
    for i in range(count):
        if verbose:
            click.echo(f"Processing {filename} ({i+1}/{count})")
    click.echo(f"Done! Format: {format}")

# Subcommands
@click.group()
def cli():
    pass

@cli.command()
@click.argument("name")
def greet(name):
    """Say hello to someone."""
    click.echo(f"Hello, {name}!")

@cli.command()
@click.argument("name")
def goodbye(name):
    """Say goodbye to someone."""
    click.echo(f"Goodbye, {name}!")

if __name__ == "__main__":
    cli()
# Usage: python app.py greet Alice
#        python app.py goodbye Bob

typer — Modern CLI with Type Hints

import typer
from typing import Optional
from enum import Enum

app = typer.Typer()

class Format(str, Enum):
    csv = "csv"
    json = "json"
    html = "html"

@app.command()
def process(
    filename: str,
    count: int = typer.Option(1, "--count", "-n"),
    verbose: bool = typer.Option(False, "--verbose", "-v"),
    format: Format = typer.Option(Format.csv),
):
    """Process a file and generate output."""
    for i in range(count):
        if verbose:
            typer.echo(f"Processing {filename} ({i+1}/{count})")
    typer.echo(f"Done! Format: {format.value}")

@app.command()
def hello(name: str, formal: bool = False):
    """Say hello to someone."""
    if formal:
        typer.echo(f"Good day, {name}.")
    else:
        typer.echo(f"Hey, {name}!")

if __name__ == "__main__":
    app()

Comparison

Featureargparseclicktyper
SetupVerboseDecoratorsType hints
Learning curveLowMediumLow
SubcommandsManualBuilt-inBuilt-in
Auto-helpYesYesYes
Shell completionNoYesYes
Best forSimple CLIsComplex CLIsModern CLIs

Key Takeaways

  1. Use argparse for simple CLIs (no dependencies)
  2. Use click for complex CLIs with many options
  3. Use typer for type-hint-based CLIs
  4. Always add --help to all commands
  5. Validate inputs early and give clear error messages
  6. Use click.echo() instead of print() for CLI output
  7. Add shell completion for better UX

Advertisement

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement