←

tenacity: reintentos con backoff exponencial para APIs de IA

Contexto

Las APIs de IA (Gemini, OpenAI, Claude) fallan con rate limits, timeouts y errores 500 intermitentes. Si tu script falla en el frame 18 de 20, pierdes todo el progreso. Necesitas reintentos automaticos pero no quieres escribir loops de retry a mano en cada llamada.

Lo que aprendi

tenacity es un decorador que agrega reintentos con una linea:

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=2, max=30),
)
async def analyze_frame(image_path: str) -> str:
    """Llama a Gemini Flash para analizar un frame."""
    response = await client.generate_content(
        contents=[image, prompt],
    )
    return response.text

Si Gemini retorna 429 (rate limit) o 500, tenacity espera 2s, luego 4s, luego 8s (exponencial) y reintenta hasta 3 veces. Si despues de 3 intentos sigue fallando, lanza la excepcion original.

Para ser mas selectivo con que errores reintentar:

from tenacity import retry_if_exception_type
import httpx

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(min=2, max=30),
    retry=retry_if_exception_type((httpx.TimeoutException, httpx.HTTPStatusError)),
)
async def call_api(prompt: str) -> str:
    ...

Tip: logging de reintentos

from tenacity import before_sleep_log
import logging

logger = logging.getLogger(__name__)

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(min=2, max=30),
    before_sleep=before_sleep_log(logger, logging.WARNING),
)

Esto loguea "Retrying call_api in 4.0 seconds..." automaticamente.

Por que importa

Una linea de decorador te ahorra horas de debugging de "por que fallo a las 3am". Lo uso en todos los scripts que llaman APIs externas. pip install tenacity y no vuelves a escribir un while True: try: manual.