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.