Buenas prácticas de errores y registro
Reglas operativas para excepciones y registros en servicios Python de producción.
Cómo usar esta lista
- Aplica primero en los límites del servicio: manejadores HTTP, puntos de entrada de CLI, workers.
- Empareja cada regla con CI (
pytest,-W error, pruebas de formato de registro). - Revisa los registros de guardia trimestralmente: si una regla no ayudó en incidentes, ajústala.
A - Excepciones
- Captura tipos de excepción específicos. Nunca uses
except:desnudo en código de aplicación. - Encadena con
raise DomainError() from excen los límites. Conserva la causa raíz en registros y Sentry. - Usa una jerarquía personalizada superficial por contexto delimitado. Los manejadores capturan
BillingError, noException. - Falla rápido ante errores de programador. Deja que
AssertionErroryTypeErrorburbujeen en desarrollo; corrige el código. - Maneja
ExceptionGroupconexcept*en códigoasyncdeTaskGroup. No asumas un fallo único.
B - Configuración de registro
- Configura el registro una vez en el punto de entrada de la aplicación. Las bibliotecas solo usan
getLogger(__name__). - Usa formato
%perezoso:log.info("id=%s", id). Evita f-strings en llamadas de registro. - Establece el nivel desde el entorno. DEBUG localmente, INFO/WARNING en producción.
- Adjunta un archivo rotatorio o envía a un agregador. stderr solo se pierde al reiniciar el contenedor.
- Silencia el ruido de terceros de forma selectiva.
urllib3,asyncio- filtra por módulo, documenta el porqué.
C - Operaciones estructuradas
- Emite JSON o
clave=valoren producción. Buscarequest_id,user_id,duration_ms. - Vincula IDs de correlación en middleware.
contextvarspara campos con ámbito de solicitud. - Registra excepciones con
log.exceptiondentro deexcept. Una pila por incidente, no impresiones duplicadas. - Mensaje de evento estático, campos dinámicos.
"payment_failed"+order_id=, no oraciones interpoladas. - Redacta secretos y PII en procesadores. Tokens y correos electrónicos nunca en campos de registro sin formato.
D - Reintentos y advertencias
- Reintenta solo fallos transitorios e idempotentes. Limita los intentos; retroceso exponencial con jitter.
- Lanza un error encadenado cuando se agotan los reintentos. Incluye el número de intento en el mensaje.
- Marca como obsoleto con
DeprecationWarningy versión de eliminación. Ejecuta CI con advertencias como errores para tu código. - Usa
stacklevel=2+en envolturas de advertencia. Culpa a la línea del llamador en el traceback. - Nunca uses advertencias para ramificación de negocio. Las advertencias notifican; las excepciones controlan el flujo.
E - Política y revisión
- No tragar silenciosamente - registrar o volver a lanzar.
suppresssolo para rutas verdaderamente opcionales. - Mapea excepciones de dominio a códigos HTTP/estado en una capa. No dispersas en repositorios.
- Prueba tipos de excepción y emisiones de advertencia.
pytest.raises,deprecated_call. - Documenta el runbook de guardia: qué consulta de registro significa qué. Enlace desde la alerta al panel.
- Revisa las tasas de error después de los lanzamientos. Los nuevos tipos de excepción deben ser esperados y documentados.
Preguntas frecuentes
¿Cuál es el peor hábito?
except: pass desnudo - oculta la corrupción de datos hasta que la conciliación falla semanas después.
¿Debo registrar y lanzar?
Sí, en los límites cuando los operadores necesitan visibilidad y los llamadores necesitan fallo - no en cada bucle interno.
¿Cómo lo aplico en CI?
ruff E722, pytest con filterwarnings=error, y pruebas de integración que afirman el esquema JSON de registro.
¿print vs logging?
print para notebooks y scripts únicos; logging para cualquier cosa desplegada.
¿Qué tan detallado debe ser INFO?
Una línea por límite de solicitud exitosa; DEBUG para internos. INFO por fila de alta cardinalidad inunda los agregadores.
¿Necesito Sentry si tengo registros?
Complementario - Sentry agrupa los stack traces; los registros proporcionan contexto cronológico. Conecta ambos con la misma etiqueta de versión.
¿Cómo manejo excepciones de terceros?
Envuelve una vez en el límite del adaptador en un error de dominio; registra el original con from exc.
¿Deben las bibliotecas registrar errores?
Las bibliotecas registran contexto en WARNING/ERROR; la aplicación decide los manejadores y el mensaje final al usuario.
¿Qué pasa con el registro en asyncio?
Usa manejadores amigables con async o cola a un hilo; evita E/S bloqueante en el hilo del bucle de eventos.
¿Cómo migro de la depuración con print?
Reemplaza con log.debug y ejecuta localmente en DEBUG; elimina antes de fusionar o controla mediante un flag.
Relacionado
- Conceptos básicos de excepciones - introducción a try/except
- Registro estructurado y contextual - detalles de JSON
- Reintentos y retroceso - políticas de reintento
- Advertencias y deprecaciones - eliminaciones suaves
Versiones de pila: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), 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+.