alpha

Python

Quick reference for Python patterns and tools

#python#cli#typer#joblib#caching#memoization

Building CLI Tools with Typer

Typer is the default choice for CLI tools. Built on Click, but with type hints instead of decorators for arguments.

uv add typer
import typer

app = typer.Typer(help="My CLI tool")

@app.command()
def greet(
    name: str = typer.Argument(..., help="Name to greet"),
    loud: bool = typer.Option(False, "--loud", "-l", help="Shout it"),
):
    """Greet someone."""
    msg = f"Hello, {name}!"
    print(msg.upper() if loud else msg)

if __name__ == "__main__":
    app()

For subcommands, create separate Typer apps and register them:

# main.py
from myapp.db.cli import app as db_app
app.add_typer(db_app, name="db")

# myapp/db/cli.py
app = typer.Typer(help="Database commands")

@app.command("ping")
def ping():
    print("PONG")

Typer over argparse: less boilerplate. Typer over Click: type hints are the API.

Joblib Memory for Disk-Based Caching

Use joblib.Memory for caching expensive function results to disk. Automatic invalidation based on function arguments. Cache persists across process restarts.

Cache Location

Cache directory MUST use Path for portability. Hardcoded strings break across environments.

# Bad
memory = Memory("cache")
memory = Memory("/tmp/cache")

# Good
from pathlib import Path
CACHE_DIR = Path.home() / ".cache" / "myapp"
memory = Memory(CACHE_DIR, verbose=0)

Function Arguments

All arguments to cached functions MUST be hashable. Strings, numbers, tuples work. Lists and dicts do not.

# Bad - list is not hashable
@memory.cache
def process(items: list) -> dict:
    ...

# Good - tuple is hashable
@memory.cache
def process(items: tuple) -> dict:
    ...

Joblib vs lru_cache

Use joblib.Memory when cache MUST persist across runs. Use functools.lru_cache for in-memory caching within a single process.

RequirementTool
Persist across runsjoblib.Memory
In-memory onlyfunctools.lru_cache
Large return values (pickled to disk)joblib.Memory
Fast, small resultsfunctools.lru_cache

Cache Invalidation

Clear cache explicitly when source data changes. Joblib does not detect external changes.

memory.clear()       # Clear all cached functions
fetch_data.clear()   # Clear specific function only

References