Logging en Python
🗺️ Mapa de la Lección
⏱ 1 hora🟡 Intermedio🎯 Qué aprenderás
- Usar el módulo logging en lugar de print()
- Entender niveles de logging (DEBUG, INFO, WARNING, ERROR, CRITICAL)
- Configurar logging para consola y archivos
- Crear loggers personalizados
- Aplicar logging en producción y desarrollo
🌍 Para qué te sirve
- Depuración: registrar eventos para entender qué pasa
- Monitoreo: rastrear comportamiento de aplicaciones en producción
- Auditoría: registrar acciones importantes del usuario
- Diagnóstico: encontrar problemas en sistemas complejos
- Análisis: analizar patrones de uso y errores
- Debugging: diferentes niveles para desarrollo vs producción
🎯 ¿Por qué aprender logging?
Cuando depuras código, probablemente usas print() para ver qué está pasando. Funciona, pero tiene problemas: no puedes controlar qué se muestra, no puedes guardar en archivo fácilmente, y no sabes la importancia de cada mensaje.
El logging es esencial porque:
- Control de niveles: diferentes niveles para desarrollo vs producción
- Persistencia: guardar logs en archivos para análisis posterior
- Organización: filtrar y buscar logs por nivel, módulo o componente
- Profesionalismo: sistemas reales usan logging, no print()
- Depuración: entender qué pasa en producción cuando no puedes depurar
🌍 Casos reales donde se usa
El logging está en todos los sistemas profesionales:
- Depuración: Registrar eventos para entender qué pasa
- Monitoreo: Rastrear comportamiento de aplicaciones en producción
- Auditoría: Registrar acciones importantes del usuario
- Diagnóstico: Encontrar problemas en sistemas complejos
- Análisis: Analizar patrones de uso y errores
- Debugging: Diferentes niveles para desarrollo vs producción
Ejemplo real: Cuando una aplicación web falla en producción, los logs te permiten ver exactamente qué pasó, cuándo, y por qué, sin necesidad de reproducir el error.
💡 Concepto base
El logging te da un sistema profesional para registrar eventos con niveles de importancia (DEBUG, INFO, WARNING, ERROR, CRITICAL), formatos personalizados, y múltiples destinos (consola, archivo, etc.).
Lo genial de Python: El módulo logging está incluido en la librería estándar y es muy potente.
import logging
# Configurar logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Usar logging en lugar de print()
logger.info("Preparando chilaquiles al pastor")
logger.warning("Se está acabando el queso")
logger.error("Se quemaron las tortillas")
INFO:__main__:Preparando chilaquiles al pastor
WARNING:__main__:Se está acabando el queso
ERROR:__main__:Se quemaron las tortillas
El logging es como el libro de recetas de un restaurante donde anotas todo lo que pasa en la cocina: qué platos se prepararon, qué ingredientes se usaron, si hubo algún problema, y cuánto tiempo tomó cada orden. En lugar de solo recordar mentalmente (como print()), tienes un registro organizado que puedes revisar después. Los niveles de logging son como diferentes tipos de notas: INFO es "preparé chilaquiles al pastor", WARNING es "se está acabando el queso", ERROR es "se quemaron las tortillas". Cada nivel tiene su importancia y propósito.
Antes de continuar: Asegúrate de entender Manejo de Excepciones. Logging y excepciones van de la mano: cuando manejas una excepción, deberías registrarla con logging para poder diagnosticar problemas después.
Conceptos Básicos
Configuración Básica
La forma más simple de empezar:
import logging
# Configuración básica (solo necesitas hacerlo una vez al inicio)
logging.basicConfig(
level=logging.INFO, # Solo muestra INFO y niveles superiores
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
# Formato: fecha - nombre - nivel - mensaje
)
# Usar logging
logging.info("Mensaje informativo")
logging.warning("Advertencia")
logging.error("Error")
Salida esperada:
2024-01-15 14:30:25,123 - root - INFO - Mensaje informativo
2024-01-15 14:30:25,124 - root - WARNING - Advertencia
2024-01-15 14:30:25,125 - root - ERROR - Error
¿Qué está pasando?
level=logging.INFOsignifica "solo muestra mensajes de nivel INFO o superior"- El formato incluye fecha/hora, nombre del logger, nivel y mensaje
logging.info(),logging.warning(), etc. son funciones para registrar eventos
Niveles de Logging (De Menor a Mayor Severidad)
Python tiene 5 niveles estándar:
# DEBUG - Detalles para depuración (más verboso)
logging.debug("Detalles internos del proceso")
# Solo se muestra si level=logging.DEBUG
# INFO - Información general del programa
logging.info("Usuario inició sesión")
# Se muestra si level=logging.INFO o superior
# WARNING - Algo inesperado pero no es un error
logging.warning("Conexión lenta detectada")
# Se muestra si level=logging.WARNING o superior
# ERROR - Error que impide una funcionalidad
logging.error("No se pudo conectar a la base de datos")
# Se muestra si level=logging.ERROR o superior
# CRITICAL - Error crítico que puede detener el programa
logging.critical("Sistema de archivos lleno")
# Siempre se muestra
¿Cuándo usar cada nivel?
- DEBUG: Detalles técnicos solo para desarrolladores
- INFO: Eventos normales del programa (usuario hizo X, proceso completado)
- WARNING: Algo raro pero el programa puede continuar
- ERROR: Algo falló pero el programa puede recuperarse
- CRITICAL: El programa puede fallar completamente
En la práctica: En desarrollo usas DEBUG, en producción INFO o WARNING.
Configuración Avanzada
Múltiples Handlers
import logging
import sys
# Crear logger
logger = logging.getLogger('mi_app')
logger.setLevel(logging.DEBUG)
# Handler para consola
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
# Handler para archivo
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)
# Formato
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
# Agregar handlers
logger.addHandler(console_handler)
logger.addHandler(file_handler)
Rotación de Logs
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
'app.log',
maxBytes=1024*1024, # 1MB
backupCount=5
)
Ejemplos de Uso
En una Aplicación
import logging
# Configuración
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('app.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
def procesar_datos(datos):
logger.info(f"Iniciando procesamiento de {len(datos)} registros")
try:
# Procesamiento
logger.debug("Detalles del procesamiento")
except Exception as e:
logger.error(f"Error en el procesamiento: {e}")
raise
Con Contexto
import logging
from contextlib import contextmanager
@contextmanager
def log_context(logger, mensaje):
logger.info(f"Iniciando: {mensaje}")
try:
yield
except Exception as e:
logger.error(f"Error en {mensaje}: {e}")
raise
finally:
logger.info(f"Finalizando: {mensaje}")
# Uso
with log_context(logger, "Procesamiento de archivo"):
# Código a ejecutar
pass
Buenas Prácticas
- Usa Nombres de Logger Específicos
logger = logging.getLogger(__name__)
- Configura Niveles Apropiados
# Desarrollo
logging.basicConfig(level=logging.DEBUG)
# Producción
logging.basicConfig(level=logging.INFO)
- Incluye Información Útil
logger.error(f"Error al procesar archivo {archivo}: {error}")
Ejemplo Práctico
import logging
import sys
from datetime import datetime
class LoggerConfig:
def __init__(self, nombre_app: str, nivel: str = "INFO"):
self.logger = logging.getLogger(nombre_app)
self.logger.setLevel(getattr(logging, nivel))
# Formato
formato = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Handler para archivo
archivo_handler = logging.FileHandler(
f"{nombre_app}_{datetime.now().strftime('%Y%m%d')}.log"
)
archivo_handler.setFormatter(formato)
# Handler para consola
consola_handler = logging.StreamHandler(sys.stdout)
consola_handler.setFormatter(formato)
# Agregar handlers
self.logger.addHandler(archivo_handler)
self.logger.addHandler(consola_handler)
def get_logger(self):
return self.logger
# Uso
logger_config = LoggerConfig("mi_app", "DEBUG")
logger = logger_config.get_logger()
logger.info("Aplicación iniciada")
logger.debug("Detalles de configuración")
logger.error("Error en operación")
Consejos
- Usa niveles de logging apropiados
- Incluye información contextual relevante
- Configura diferentes handlers para diferentes propósitos
- Considera la rotación de logs en producción
Recursos Adicionales
Documentación Oficial
- Documentación oficial de logging
- Logging Cookbook
- Buenas Prácticas de Logging
- PEP 282 - A Logging System
Bibliografía Recomendada
- Python Tricks (Dan Bader) - Capítulo sobre logging y debugging
- Effective Python (Brett Slatkin) - Item 57: Consider Interactive Debugging with pdb
- Python Cookbook, 3rd Ed (Beazley & Jones) - Recetas sobre logging
- The Pragmatic Programmer (Thomas & Hunt) - Capítulo sobre logging y monitoreo
- Site Reliability Engineering (Google) - Capítulos sobre logging en producción
Conceptos Relacionados
- Excepciones - Maneja errores que luego registras
- Type Hints - Documenta tipos junto con logging
- Testing - Usa logging en tests