Typer
Typer genera CLIs a partir de type hints de Python. Construido sobre Click, reduce el código repetitivo manteniendo el ecosistema de Click.
Receta
import typer
app = typer.Typer()
@app.command()
def greet(name: str, loud: bool = False):
msg = f"Hello, {name}"
typer.echo(msg.upper() if loud else msg)
if __name__ == "__main__":
app()Cuándo usar esto:
- El proyecto ya utiliza type hints en todo el código.
- Prototipado rápido de CLIs a partir de firmas de funciones.
- El poder de Click con menos boilerplate de decoradores.
Ejemplo funcional
import typer
from pathlib import Path
from typing import Optional
from enum import Enum
app = typer.Typer(help="CLI de gestión de facturas")
class OutputFormat(str, Enum):
json = "json"
csv = "csv"
@app.command()
def export(
invoice_id: int = typer.Argument(..., help="ID de la factura"),
output: Path = typer.Option("out.json", help="Archivo de salida"),
format: OutputFormat = OutputFormat.json,
verbose: bool = typer.Option(False, "--verbose", "-v"),
):
if verbose:
typer.echo(f"Exportando factura {invoice_id} como {format.value}", err=True)
# Lógica de exportación
typer.echo(f"Escrito en {output}")
@app.command()
def list(limit: int = typer.Option(10, min=1, max=100)):
typer.echo(f"Listando {limit} facturas")
if __name__ == "__main__":
app()Lo que esto demuestra:
- Los type hints controlan los tipos de argumentos y el texto de ayuda.
Enumse convierte automáticamente enChoice.Pathvalida rutas de archivos.typer.Optionytyper.Argumentpara metadatos.
Análisis detallado
Mapeo de tipos
| Type hint | Comportamiento de la CLI |
|---|---|
str | Argumento de cadena |
int | Entero con validación |
bool | Flag (por defecto False) |
Optional[str] | Opción opcional |
Enum | Opción entre los valores del enum |
Path | Ruta de archivo/directorio |
Errores comunes
- Type hints faltantes - Typer no puede inferir argumentos. Solución: Anota cada parámetro.
- Validación compleja - los hints no son suficientes. Solución: Usa modelos Pydantic o validadores de callback.
- Confusión con flags booleanos posicionales -
boolcomo posicional es complicado. Solución: Usatyper.Optionpara flags. - No instalar typer[all] - faltan extras de autocompletado de shell. Solución:
uv add "typer[all]"para desarrollo. - Cambios incompatibles entre versiones de Typer - fija la versión. Solución: Bloquea la versión en
pyproject.toml.
Alternativas
| Alternativa | Usar cuando | No usar cuando |
|---|---|---|
| Click | Se necesita más control sobre el parseo | Los type hints cubren tus necesidades |
| argparse | Cero dependencias | Se desea una CLI basada en tipos |
| cyclopts | Configuración pesada con dataclasses | Comandos de función simples |
Preguntas frecuentes
¿Typer o Click?
Typer para proyectos con type hints. Click para control detallado.
¿Cómo pruebo Typer?
from typer.testing import CliRunner (mismo patrón que Click).
¿Subcomandos?
app = typer.Typer() + sub = typer.Typer() + app.add_typer(sub, name="db").
¿Integración con Pydantic?
Usa modelos Pydantic como tipos para configuración estructurada (Typer 0.12+).
¿Cómo añado ayuda?
typer.Argument(help="...") o docstrings en los comandos.
¿Autocompletado de shell?
typer[all] incluye autocompletado. Instalar mediante --install-completion.
¿Comandos asíncronos?
Usa async def con el soporte asíncrono de typer 0.9+ o envuelve con asyncio.run.
¿Múltiples comandos en una app?
Múltiples funciones decoradas con @app.command().
¿Cómo manejo archivos de configuración?
Carga la configuración por separado; Typer maneja los argumentos de la CLI. Considera pydantic-settings.
¿Está Typer listo para producción?
Sí. Potencia la CLI de FastAPI. Construido sobre la base estable de Click.
Relacionado
- Click - framework subyacente
- argparse - opción de la librería estándar
- Configuración y Entorno - ajustes
- Mejores prácticas para CLIs - reglas de diseño
Versiones de Stack: Esta página fue escrita para Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.