---
name: python-automation
description: Escribe scripts de automatización y procesamiento de datos en Python que se puedan reejecutar sin miedo. Úsala al crear scripts de CLI, tareas programadas, tratamiento de ficheros o integraciones con APIs y LLMs.
version: 1.0.0
license: CC-BY-4.0
updated: 2026-08-16
---

# Python: scripts de automatización

Un script de automatización se ejecuta desatendido y a menudo sobre datos
reales. Estas reglas evitan los desastres silenciosos.

## Esqueleto

```python
#!/usr/bin/env python3
"""Descripción en una línea de lo que hace el script."""
from __future__ import annotations

import argparse
import logging
import sys
from pathlib import Path

log = logging.getLogger(Path(__file__).stem)


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("origen", type=Path)
    parser.add_argument("--dry-run", action="store_true",
                        help="muestra lo que haría sin escribir nada")
    parser.add_argument("-v", "--verbose", action="store_true")
    args = parser.parse_args(argv)

    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.INFO,
        format="%(levelname)s %(name)s: %(message)s",
    )

    if not args.origen.exists():
        log.error("no existe: %s", args.origen)
        return 1

    return 0


if __name__ == "__main__":
    sys.exit(main())
```

## Reglas

1. **`--dry-run` en todo lo que escriba, borre o publique.** Es la diferencia
   entre un fallo y un incidente.
2. **`pathlib` en lugar de `os.path`**, y nunca concatenación de rutas con `+`.
3. **`logging`, no `print`.** El script acabará en cron o en CI, donde `print`
   se pierde y no lleva marca de tiempo.
4. **Código de salida honesto**: `0` solo si todo fue bien. Un script que
   siempre devuelve `0` rompe cualquier automatización que lo encadene.
5. **Idempotencia**: ejecutarlo dos veces debe dejar el mismo estado. Si no es
   posible, escribe primero a un fichero temporal y renombra al final.

## Entorno y dependencias

```bash
uv venv && uv pip install -r requirements.txt   # o python -m venv .venv
```

- Fija las versiones en `requirements.txt`. Un script que funcionaba en marzo y
  falla en junio suele ser una dependencia que subió de major.
- Secretos por variables de entorno (`os.environ["API_KEY"]`, que falla fuerte
  si no está) o `.env` fuera del control de versiones. Nunca en el código.

## Ficheros y datos

- CSV/JSON: abre siempre con `encoding="utf-8"` explícito; el valor por defecto
  en Windows no es UTF-8 y el script se romperá solo en esa máquina.
- Para volúmenes grandes, itera en streaming en lugar de cargar todo en
  memoria: `for line in f` antes que `f.readlines()`.

## Llamadas a APIs y LLMs

- `timeout=` obligatorio en toda petición HTTP: sin él, un cuelgue del servidor
  bloquea el script para siempre.
- Reintentos con espera exponencial solo en errores 429 y 5xx; un 4xx no se
  arregla repitiendo.
- Cachea las respuestas caras en disco durante el desarrollo: iterar sobre el
  prompt no debería costar una llamada de pago cada vez.
