Logging en Python: guía completa para principiantes

Publicado el: 11/07/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

    2 balões de comentários em um fundo laranja
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Comentarios en Python: buenas prácticas y ejemplos

    Aprende a escribir comentarios en Python que expliquen decisiones, TODO, seguridad y algoritmos, y a diferenciarlos de docstrings y código

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Pessoa programando em um notebook, vista de trás, com código desfocado exibido na tela em um fundo escuro
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Docstrings en Python: cómo documentar tu código

    Aprende docstrings en Python para funciones, clases y módulos: parámetros, retornos, excepciones, ejemplos, PEP 257, pydoc y buenas prácticas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Logo do Python com o texto 'PEP 8' sobre fundo azul escuro, representando o guia de estilo da linguagem
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    PEP 8 en Python: guía para escribir código limpio

    Aprende PEP 8 en Python: nombres, sangría, imports, espacios, líneas, funciones, comentarios, docstrings, linters y refactorización.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026