Introducción al módulo logging
El módulo logging en Python proporciona un sistema flexible para registrar eventos en aplicaciones. Su objetivo principal es documentar sucesos relevantes durante la ejecución del programa, facilitando el diagnóstico y la depuración de problemas posteriores. Este módulo permite diferentes niveles de severidad y múltiples destinos de salida.
Niveles de registro
El módulo define cinco niveles de registro, que corresponden a diferentes gravedades:
debug(nivel 10): Información detallada, típicamente para diagnósticos.info(nivel 20): Confirmación de que las cosas funcionan como se espera.warning(nivel 30): Indicación de que algo inesperado ocurrió, pero el programa sigue ejecutándose.error(nivel 40): Debido a un problema más grave, el programa no pudo realizar una función.critical(nivel 50): Un error grave que puede impedir que el programa continúe.
Por defecto, solo se muestran los mensajes de nivel warning y superiores en la consola. Esto se puede configurar para filtrar la salida según sea necesario.
Componentes del sistema de registro
El módulo opera con cuatro copmonentes clave:
- Generador de registros (logger): Crea mensajes de registro.
- Filtro de registros (filter): Determina qué mensajes se emiten (requiere implementación orientada a objetos).
- Formateador (formatter): Define la estructura y el formato de los mensajes.
- Manejador (handler): Envía los registros formateados a destinos específicos, como archivos o la consola.
Configuración básica
Para personalizar el comportamiento, se puede crear un generador de registros con parámetros específicos. A continuación, un ejemplo que modifica la estructura y lógica del código original:
import logging
# Crear un generador con un identificador único
registrador = logging.getLogger('aplicacion_principal')
# Establecer el nivel mínimo de registro usando constantes
registrador.setLevel(logging.WARNING)
# Definir un manejador para escribir en un archivo
manejador_archivo = logging.FileHandler('registro_actividad.log', mode='a', encoding='utf-8')
# Personalizar el formato de los mensajes
estructura = logging.Formatter('%(asctime)s - %(name)s - %(filename)s - %(message)s')
# Asociar el formato al manejador
manejador_archivo.setFormatter(estructura)
# Vincular el manejador al generador
registrador.addHandler(manejador_archivo)
# Generar un mensaje de error
registrador.error('Se produjo un fallo en el módulo de cálculo.')
Los formatos disponibles incluyen variables como %(asctime)s para la marca de tiempo, %(name)s para el nombre del generador, y %(message)s para el contenido del mensaje.
Configuración mediante diccionario
Para una gestión más centralizada, se puede utilizar un diccionario de configuración. Este enfoque permite definir múltiples manejadores y formatos de manera estructurada. A continuación, se muestra un ejemplo reescrito con nombres de variables y lógica alterada:
from mi_config import ajustes
# Definir formatos de registro
formato_detallado = '[%(asctime)s][%(threadName)s:%(thread)d][id_tarea:%(name)s][%(filename)s:%(lineno)d][%(levelname)s][%(message)s]'
formato_simple = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
# Estructura de configuración para el módulo logging
CONFIGURACION_LOG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'detallado': {
'format': formato_detallado
},
},
'filters': {},
'handlers': {
'salida_consola': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'detallado'
},
'archivo_rotativo': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'formatter': 'detallado',
'filename': ajustes.RUTA_REGISTRO,
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'encoding': 'utf-8',
},
},
'loggers': {
'': {
'handlers': ['archivo_rotativo', 'salida_consola'],
'level': 'DEBUG',
},
},
}
# Aplicar la configuración
import logging.config
logging.config.dictConfig(CONFIGURACION_LOG)
# Usar un generador con nombre específico
registrador_aplicacion = logging.getLogger('modulo_financiero')
registrador_aplicacion.debug('Depuración del módulo financiero iniciada.')
En esta configuración, se establece un generador raíz (clave vacía) que captura todos los mensajes. Los generadores con nombres específicos heredarán esta configuración si no se define una propia, permitiendo flexibilidad en sistemas con múltiples módulos.