Logging: registra errores y eventos en Python

Actualizado el: 20/08/2026
Tempo de leitura: 5 minutos
Configuração de logs em aplicações Python usando logging

El logging en Python permite registrar lo que ocurre durante la ejecución de un programa. En lugar de depender de mensajes temporales con print(), puedes clasificar eventos por gravedad, añadir fechas, guardar registros en archivos y conservar tracebacks completos cuando ocurre un error.

Esta herramienta resulta especialmente útil en automatizaciones, aplicaciones web, tareas programadas y proyectos que se ejecutan sin una persona observando el terminal. El módulo forma parte de la biblioteca estándar, por lo que no requiere instalación.

Logging frente a print()

print() es adecuado para mostrar información al usuario o hacer una comprobación rápida. Logging está diseñado para diagnóstico y operación:

  • incluye niveles como DEBUG, INFO y ERROR;
  • añade fechas y nombres de módulos;
  • puede escribir en varios destinos;
  • filtra mensajes según el entorno;
  • registra excepciones con traceback;
  • rota archivos para controlar su tamaño.

La guía de print() en Python explica cuándo la salida normal sigue siendo la mejor opción.

Los niveles de logging

Python define cinco niveles habituales:

  • DEBUG: detalles técnicos para investigar el estado interno.
  • INFO: operaciones normales completadas correctamente.
  • WARNING: una situación inesperada que no detuvo el programa.
  • ERROR: una operación concreta no pudo completarse.
  • CRITICAL: un fallo grave puede impedir que la aplicación continúe.

Por defecto, el logger raíz muestra WARNING y niveles superiores. Por eso un mensaje INFO puede no aparecer hasta configurar el sistema.

Primer ejemplo

import logging

logging.basicConfig(level=logging.DEBUG)

logging.debug("Información detallada")
logging.info("La aplicación comenzó")
logging.warning("Queda poco espacio")
logging.error("No se pudo procesar el archivo")
logging.critical("La aplicación no puede continuar")

El nivel configurado funciona como umbral. Con logging.ERROR, solamente se emitirían ERROR y CRITICAL.

El Logging HOWTO oficial de Python presenta la configuración básica y patrones recomendados.

Formatear los mensajes

import logging

logging.basicConfig(
    level=logging.INFO,
    format=(
        "%(asctime)s | %(levelname)s | "
        "%(name)s | %(message)s"
    ),
)

logging.info("Aplicación preparada")

Campos frecuentes:

  • %(asctime)s: fecha y hora;
  • %(levelname)s: nivel;
  • %(name)s: nombre del logger;
  • %(module)s: módulo que creó el mensaje;
  • %(lineno)d: línea del código;
  • %(message)s: texto final.

Añadir valores sin f-strings

La API de logging admite formato diferido:

user_id = 417
filename = "report.csv"

logging.info(
    "El usuario %s comenzó a procesar %s",
    user_id,
    filename,
)

El mensaje se formatea solamente si supera los filtros. Esto evita trabajo innecesario en mensajes DEBUG desactivados.

Guardar logs en un archivo

import logging

logging.basicConfig(
    filename="application.log",
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(message)s",
    encoding="utf-8",
)

logging.info("Importación iniciada")
logging.error("No se pudo guardar el registro 208")

Una ruta relativa se resuelve desde el directorio actual, que puede diferir de la carpeta del script. La guía de pathlib en Python explica cómo construir una ruta explícita y portable.

El modo predeterminado añade mensajes al archivo. Utiliza filemode="w" solo cuando realmente quieras reemplazar el historial en cada ejecución.

Registrar excepciones y tracebacks

import logging

try:
    result = 10 / 0
except ZeroDivisionError:
    logging.exception("Error durante el cálculo")

logging.exception() emite un ERROR e incluye automáticamente el traceback actual. Debe utilizarse normalmente dentro de un bloque except.

Logging no sustituye el manejo de errores. Primero decide si debes recuperar, reintentar, omitir o propagar. La guía de try y except en Python explica ese control de flujo.

Crear un logger por módulo

import logging

logger = logging.getLogger(__name__)


def load_configuration():
    logger.info("Cargando configuración")

__name__ identifica el módulo, lo que permite distinguir mensajes de shop.payments y shop.inventory. Una práctica habitual es que los módulos creen loggers y que el punto de entrada configure handlers y niveles.

Handlers y formatters

El logger crea registros. Un handler decide el destino y un formatter define la apariencia. El siguiente ejemplo muestra INFO en la consola y guarda DEBUG en un archivo:

import logging

logger = logging.getLogger("inventory")
logger.setLevel(logging.DEBUG)

console = logging.StreamHandler()
console.setLevel(logging.INFO)

file_handler = logging.FileHandler(
    "inventory.log",
    encoding="utf-8",
)
file_handler.setLevel(logging.DEBUG)

formatter = logging.Formatter(
    "%(asctime)s | %(levelname)s | "
    "%(name)s | %(message)s"
)

console.setFormatter(formatter)
file_handler.setFormatter(formatter)

logger.addHandler(console)
logger.addHandler(file_handler)

logger.debug("Cálculo detallado")
logger.info("Inventario actualizado")

La consola recibe el evento INFO. El archivo recibe INFO y DEBUG.

Evitar mensajes duplicados

Los duplicados suelen aparecer cuando se añaden handlers varias veces o cuando un registro se propaga a un logger padre que también tiene handlers.

Configura el sistema una sola vez, durante el inicio. Para un logger completamente aislado, puedes utilizar:

logger.propagate = False

No desactives la propagación sin entender la jerarquía, porque la configuración central depende de ella en muchos proyectos.

Rotar archivos de log

import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger("service")
logger.setLevel(logging.INFO)

handler = RotatingFileHandler(
    "service.log",
    maxBytes=1_000_000,
    backupCount=3,
    encoding="utf-8",
)

handler.setFormatter(
    logging.Formatter(
        "%(asctime)s | %(levelname)s | %(message)s"
    )
)

logger.addHandler(handler)
logger.info("Servicio iniciado")

Cuando el archivo alcanza aproximadamente un megabyte, comienza uno nuevo y conserva hasta tres copias anteriores. Para rotación por tiempo existe TimedRotatingFileHandler.

Ejemplo práctico de automatización

import logging
from pathlib import Path

logging.basicConfig(
    filename="organizer.log",
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(message)s",
    encoding="utf-8",
)

source = Path("incoming")
processed = 0
failed = 0

logging.info("Proceso iniciado")

for path in source.iterdir():
    if not path.is_file():
        continue

    try:
        size = path.stat().st_size
        logging.debug(
            "Archivo detectado: %s, %s bytes",
            path.name,
            size,
        )
        processed += 1
    except OSError:
        failed += 1
        logging.exception(
            "No se pudo procesar %s",
            path,
        )

logging.info(
    "Proceso terminado: %s correctos, %s fallos",
    processed,
    failed,
)

La guía de automatización con Python presenta scripts donde un historial como este resulta indispensable.

Configuración mediante diccionarios

Para aplicaciones grandes, logging.config.dictConfig() permite declarar loggers, handlers y formatos en una estructura central:

import logging.config

CONFIG = {
    "version": 1,
    "formatters": {
        "standard": {
            "format": "%(asctime)s %(levelname)s %(name)s %(message)s",
        }
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "standard",
            "level": "INFO",
        }
    },
    "root": {
        "handlers": ["console"],
        "level": "INFO",
    },
}

logging.config.dictConfig(CONFIG)

Seguridad y privacidad

No registres contraseñas, tokens, claves privadas, cookies de sesión, números completos de tarjetas ni datos personales innecesarios. Los logs suelen copiarse, archivarse y enviarse a servicios externos.

Utiliza identificadores internos, enmascara valores y define políticas de retención. Un mensaje útil describe el evento sin exponer secretos.

Depuración y logging

Logging conserva un historial, mientras que un depurador permite detener el programa e inspeccionar variables. Son herramientas complementarias. La guía de depuración de Python en VS Code explica breakpoints y seguimiento paso a paso.

Errores frecuentes

  • Llamar a basicConfig() después de emitir mensajes.
  • Registrar todo con el mismo nivel.
  • Usar logger.error() sin traceback en errores inesperados.
  • Añadir handlers repetidamente.
  • Guardar datos sensibles.
  • No rotar archivos de procesos permanentes.
  • Escribir mensajes vagos sin identificadores útiles.

Referencia oficial

La referencia oficial del módulo logging documenta loggers, handlers, filtros, formatters y configuración.

Conclusión

Logging convierte mensajes aislados en un registro operativo. Empieza con niveles y basicConfig(), añade fechas y contexto, guarda los eventos importantes en archivos y utiliza logger.exception() para fallos inesperados. En proyectos grandes, configura handlers una sola vez y crea un logger por módulo.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Configuración TOML en un proyecto Python
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    tomllib en Python: lee archivos TOML

    Aprende a leer TOML con tomllib en Python, validar configuraciones, gestionar errores y organizar proyectos con pyproject.toml.

    Ler mais

    Tempo de leitura: 6 minutos
    24/07/2026
    Desarrollador monitoreando registros estructurados en Python
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Observabilidad en Python con structlog

    Aprende observabilidad en Python con structlog, eventos JSON, contexto, pruebas, control de volumen y recomendaciones para producción.

    Ler mais

    Tempo de leitura: 5 minutos
    24/07/2026
    Configuración segura de aplicaciones Python con Pydantic Settings
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Pydantic Settings: configuración segura

    Aprende a validar variables de entorno, organizar configuraciones y proteger secretos en proyectos Python con Pydantic Settings.

    Ler mais

    Tempo de leitura: 5 minutos
    23/07/2026
    Desenvolvedor programando em Python com Ruff para lint e formatação
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Ruff: lint y formato de código Python

    Aprende Ruff en Python para lint, formato, correcciones automáticas, pyproject.toml, VS Code y CI con una configuración práctica.

    Ler mais

    Tempo de leitura: 10 minutos
    22/07/2026
    Dicas para melhorar performance de scripts Python lentos
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    ¿Por qué Python es lento? Causas y optimización

    Descubre por qué Python puede ser lento y mejora su rendimiento con cProfile, algoritmos, sets, generadores, NumPy, caché y concurrencia.

    Ler mais

    Tempo de leitura: 5 minutos
    12/07/2026
    Leitura segura de senhas no terminal usando Python
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    getpass: lee contraseñas en terminal con Python

    Lee contraseñas de forma segura con getpass, valida entradas, evita logs y texto plano y almacena credenciales con hashing adecuado.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026