Tutorial de registro de Loguru Python: Configuración sin configuración
Aprende Loguru, el marco de registro más sencillo de Python. Controla la rotación de archivos maestros, el registro estructurado, la gestión de excepciones y los sumideros personalizados sin necesidad de configuración.
Has estado depurando con instrucciones « print() » durante toda tu vida como programador. Quizás hayas probado el módulo de registro de Python una o dos veces, pero hayas vuelto a los prints porque son más sencillos.
En realidad, hay algo mejor que es igual de fácil de usar.
Las declaraciones de impresión no se pueden guardar en archivos ni activar y desactivar fácilmente. El registro integrado de Python puede hacer estas cosas, pero requiere escribir código de configuración más largo que tu programa real.
Loguru adopta un enfoque diferente: el registro debe ser tan fácil como imprimir, pero mucho más útil. Obtienes colores en tu terminal, marcas de tiempo automáticas y la posibilidad de guardar todo en archivos sin escribir una sola línea de configuración.
En este tutorial, te mostraré ejemplos prácticos que hacen que el registro sea algo natural en lugar de una tarea pesada. Descubrirás funciones que probablemente no conocías, utilizando patrones de código que facilitan la depuración.
Si eres nuevo en la depuración de Python o deseas reforzar tus habilidades básicas,adquirir unos fundamentos sólidos de Python te ayudará a comprender cuándo y por qué es necesario el registro.
Primeros pasos con Loguru: Magia sin configuración
Para instalar Loguru solo hay que ejecutar un comando:
Con el módulo logging normal, tendrías que configurar controladores, formateadores y todo lo demás antes de ver un solo mensaje de registro.
Para una comparación más detallada de los métodos de registro integrados en Python, consulta estetutorial completo sobre registro que cubre los métodos tradicionales.
Con Loguru, solo tienes que importar y empezar a registrar:
from loguru import logger
# Instead of print("Processing user data...")
logger.info("Processing user data...")# Instead of print(f"Found {count} records")
logger.info("Found {} records", count)Con la tecnología de
La salida aparece en tu terminal con colores, marcas de tiempo y niveles de registro automáticamente. No requiere configuración.
Supongamos que estás creando un sencillo rastreador web. Así es como cambia la depuración:
import requests
from loguru import logger
defscrape_website(url):
logger.info("Starting scrape for {}", url)
response = requests.get(url)
logger.debug("Response status: {}", response.status_code)if response.status_code ==200:
logger.success("Successfully scraped {} characters",len(response.text))return response.text
else:
logger.error("Failed to scrape {}: status {}", url, response.status_code)returnNoneCon la tecnología de
Observa los diferentes niveles de registro (info, debug, success, error) y el formato con llaves. Todo funciona inmediatamente sin archivos de configuración ni código de instalación.
Registro y rotación de archivos simplificados
Cuando depuras con la salida de la consola, pierdes todo en el momento en que cierras el terminal. No puedes buscar lo que ocurrió hace una hora y, si tu script se bloquea durante la noche, no hay rastro de lo que ha fallado. Tampoco puedes compartir fácilmente los resultados de la depuración con tus compañeros de equipo cuando solicitas ayuda.
El registro de archivos resuelve este problema guardando todo de forma permanente.
El registro tradicional te obliga a escribir código de configuración para configurar los controladores de archivos. Debes especificar las rutas de los archivos, crear directorios y gestionar los permisos. Con Loguru, añadir el registro de archivos es, literalmente, una línea:
from loguru import logger
# Add file logging alongside console output
logger.add("app.log")
logger.info("This appears in both console and file")
logger.error("So does this error message")Con la tecnología de
Ahora todo se guarda en app.log y sigue apareciendo en tu terminal.
Pero los archivos de registro se vuelven enormes con el tiempo. Una aplicación web que se ejecuta durante días puede generar gigabytes de registros que, con el tiempo, llenarán tu disco. La rotación de archivos resuelve este problema creando automáticamente nuevos archivos de registro cuando se cumplen determinadas condiciones. El archivo antiguo se renombra con una marca de tiempo y se crea un archivo nuevo:
# When app.log reaches 10 MB, it becomes app_2024-07-15_14-30-25.log# and a new empty app.log starts
logger.add("app.log", rotation="10 MB")# Or start a new file every day at midnight
logger.add("app.log", rotation="00:00")Con la tecnología de
Las marcas de tiempo predeterminadas funcionan, pero a menudo están en UTC o son difíciles de leer. Loguru te permite personalizar los formatos de fecha y hora según tus necesidades:
# Custom timestamp format that's easier to read
logger.add("app.log",format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
rotation="1 day")Con la tecnología de
Para los sistemas de producción, necesitas un mayor control sobre los archivos antiguos. El registro de producción requiere seguir las prácticas recomendadas de Python para garantizar que tus registros sean mantenibles y seguros. Sin gestión, los archivos de registro se acumulan y consumen almacenamiento:
# Keep only the last 10 rotated files, compress the rest
logger.add("production.log",
rotation="50 MB",# New file every 50MB
retention=10,# Keep only 10 old files
compression="zip")# Compress rotated filesCon la tecnología de
Veamos esto en un escenario realista. Estás creando un canal de datos que procesa varios archivos CSV cada noche, limpiando y validando los datos de los clientes antes de cargarlos en tu base de datos. Debes realizar un seguimiento de los archivos que se han procesado correctamente y detectar cualquier problema de calidad de los datos:
import pandas as pd
from loguru import logger
# Production-ready file logging setup
logger.add("data_processing_{time:YYYY-MM-DD}.log",
rotation="00:00",# New file daily
retention="1 week",# Keep 1 week of logsformat="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}")defprocess_csv_files(file_list):
logger.info("Starting batch processing of {} files",len(file_list))for filename in file_list:try:
df = pd.read_csv(filename)
logger.info("Loaded {} with {} rows", filename,len(df))# Your processing logic here
processed_df = df.dropna()
logger.success("Processed {} - kept {} rows", filename,len(processed_df))except Exception as e:
logger.error("Failed to process {}: {}", filename,str(e))
logger.info("Batch processing complete")Con la tecnología de
Tus registros se guardan con marcas de tiempo legibles, los archivos se rotan automáticamente y los registros antiguos se limpian solos. Puedes revisar lo que sucedió días después o enviar archivos de registro a tus compañeros de trabajo cuando solucionen problemas.
Registro estructurado para aplicaciones modernas
Cuando ejecutas una aplicación web, tus registros se convierten rápidamente en un caos de información mezclada. Las acciones de los usuarios, las consultas a la base de datos, las llamadas a la API y los errores se mezclan en un muro de texto. No puedes filtrar fácilmente por usuarios específicos, rastrear solicitudes individuales ni analizar automáticamente registros para sistemas de supervisión.
Las aplicaciones basadas en datos se benefician especialmente del registro estructurado. Si trabajas con canalizaciones de datos o análisis, desarrollar habilidades de analista de datos te ayudará a comprender qué información debes capturar en tus registros.
El registro tradicional basado en cadenas empeora aún más la situación. Todos los mensajes de registro son solo texto, por lo que extraer datos significativos requiere patrones de expresiones regulares complejos o búsquedas manuales.
El registro estructurado cambia esto al tratar las entradas de registro como objetos de datos en lugar de solo texto. Cada entrada del registro se convierte en un registro estructurado con campos que se pueden buscar, lo que facilita la consulta y el análisis mediante programación.
Registro estructurado JSON con serialize=True
Loguru simplifica el registro estructurado con la opción «serialize=True » (Registro estructurado):
from loguru import logger
# Enable JSON structured logging
logger.add("api.log", serialize=True)
logger.info("User login", user_id=123, ip_address="192.168.1.1")
logger.error("Payment failed", user_id=123, amount=99.99, error_code="INSUFFICIENT_FUNDS")Con la tecnología de
El parámetro « serialize=True » indica a Loguru que genere JSON en lugar de texto sin formato. En lugar de frases legibles, tu archivo de registro ahora contiene datos estructurados:
{"text":"User login","record":{"time":"2024-07-15T14:30:25","level":{"name":"INFO"},"extra":{"user_id":123,"ip_address":"192.168.1.1"}}}Con la tecnología de
Este formato funciona perfectamente con herramientas de análisis de registros que pueden buscar y filtrar datos JSON automáticamente.
Enlace de contexto
Pero las aplicaciones web necesitan algo más que datos estructurados. Necesitas contexto que conecte las entradas de registro relacionadas. Al procesar una solicitud de usuario, es conveniente que todos los registros relacionados compartan información común, como el ID de usuario o el ID de sesión.
El enlace de contexto resuelve esto adjuntando información persistente a tu registrador mediante logger.bind():
from loguru import logger
defprocess_user_order(user_id, order_data):# Create a logger with attached context
order_logger = logger.bind(user_id=user_id, order_id=order_data['id'])
order_logger.info("Starting order processing")
order_logger.debug("Validating payment method", method=order_data['payment'])
order_logger.info("Order processing complete", total=order_data['total'])Con la tecnología de
Ahora, todos los registros de order_logger incluyen automáticamente user_id y order_id, lo que facilita el seguimiento de todos los registros relacionados con un pedido específico.
Múltiples sumideros para diferentes salidas
Las aplicaciones modernas también necesitan diferentes salidas de registro para diferentes fines. Es posible que desees registros de consola legibles durante el desarrollo, pero registros JSON para la supervisión de la producción. En Loguru, cada destino de salida se denomina «sumidero», es decir, un lugar al que fluyen los mensajes de registro.
Loguru te permite añadir múltiples sumideros con diferentes formatos y reglas:
from loguru import logger
import sys
# Remove the default console output
logger.remove()# Sink 1: Human-readable console for development
logger.add(sys.stdout,
level="DEBUG",format="<green>{time:HH:mm:ss}</green> | {level} | {message}")# Sink 2: JSON file for production monitoring
logger.add("app.log",
serialize=True,
level="INFO")# Sink 3: Error-only file for alerts
logger.add("errors.log",
level="ERROR")Con la tecnología de
La llamada logger.remove() elimina la salida predeterminada de la consola de Loguru para que puedas configurar la tuya propia. Cada logger.add() crea un nuevo sumidero con sus propias reglas sobre lo que se registra y cómo se formatea.
Ahora las mismas sentencias de registro producen resultados diferentes:
logger.debug("Processing started")# Only appears in console
logger.info("User data loaded")# Appears in console and app.log
logger.error("Database connection failed")# Appears in all three placesCon la tecnología de
Ejemplo completo de Loguru: Sistema de registro de usuarios
Veamos esto con un ejemplo más sencillo y realista del uso de Loguru: un sistema básico de registro de usuarios.
from loguru import logger
import sys
# Set up multiple outputs
logger.remove()
logger.add(sys.stdout, level="INFO",format="{time:HH:mm:ss} | {message}")
logger.add("user_registration.log", serialize=True, level="INFO")
logger.add("errors.log", level="ERROR")defregister_user(email, password):# Create logger with user context
user_logger = logger.bind(email=email)
user_logger.info("Starting user registration")# Validate emailif"@"notin email:
user_logger.error("Invalid email format")returnFalse# Check if user exists
user_logger.debug("Checking if user already exists")# Simulate password hashing
user_logger.debug("Hashing password")# Save to database
user_logger.info("Saving user to database")
user_logger.success("User registration completed")returnTrue# Usage
register_user("[email protected]","secure123")Con la tecnología de
Esta configuración te proporciona una salida de consola legible durante el desarrollo, registros JSON estructurados para la supervisión automatizada y registros de errores independientes para las alertas. El método `bind() ` garantiza que todos los registros de cada registro de usuario incluyan la dirección de correo electrónico, lo que facilita enormemente la depuración.
Gestión de excepciones Loguru
Cuando tu código falla, normalmente obtienes un seguimiento básico de la pila que te indica dónde se ha producido el error, pero no te da mucha información sobre el motivo. Pierdes los valores de las variables en el momento del bloqueo, lo que dificulta comprender qué ha fallado. El manejo tradicional de excepciones también requiere que envuelvas todo en bloques try-catch y registres manualmente cada excepción.
Esto resulta especialmente doloroso cuando se depuran problemas de producción. Los usuarios informan de errores, pero tú no puedes reproducirlos porque no conoces el contexto en el que se produjeron.
Loguru resuelve esto con la captura automática de excepciones y trazas mejoradas que te muestran exactamente qué estaba sucediendo en tu código cuando surgieron los problemas.
Captura automática de excepciones con @logger.catch
El decorador ` @logger.catch ` captura automáticamente cualquier excepción que se produzca en una función y la registra con todo el contexto. Los decoradores como @logger.catch son unconcepto intermedio de Python que puede transformar la forma en que gestionas los errores en tu código base:
from loguru import logger
@logger.catchdefdivide_numbers(a, b):
result = a / b
return result
# This automatically logs the exception with full traceback
result = divide_numbers(10,0)Con la tecnología de
En lugar de que tu programa se bloquee con un mensaje de error básico, Loguru captura la excepción y la registra con información detallada, mientras tu programa sigue ejecutándose. El decorador funciona en cualquier función: métodos de clase, funciones asíncronas o funciones normales.
Rastreos mejorados con inspección de variables
Pero Loguru va más allá con trazas mejoradas que muestran los valores de las variables en cada nivel de la pila de llamadas. Esta función se llama «diagnóstico» y es como tener un depurador integrado en tus registros:
from loguru import logger
# Enable enhanced tracebacks
logger.add("debug.log", diagnose=True)@logger.catchdefprocess_user_data(users):for user in users:
age = user['age']if age >0:
years_to_retirement =65- age
print(f"User {user['name']} has {years_to_retirement} years to retirement")# When this crashes, you'll see the exact values of 'users', 'user', and 'age'
users_data =[{"name":"Alice","age":30},{"name":"Bob","age":"invalid"},# This will cause an error]
process_user_data(users_data)Con la tecnología de
Con «diagnose=True », cuando la función se bloquea al intentar restar una cadena de un número, Loguru te muestra exactamente qué había en cada variable:
TypeError: unsupported operand type(s) for -: 'int' and 'str'
Variables values:
users = [{"name": "Alice", "age": 30}, {"name": "Bob", "age": "invalid"}]
user = {"name": "Bob", "age": "invalid"}
age = "invalid"Con la tecnología de
Este nivel de detalle agiliza considerablemente la depuración, ya que permite ver exactamente qué datos han causado el problema.
Gestión de excepciones respetuosa con el medio ambiente
Sin embargo, los rastreos mejorados pueden exponer información confidencial, como contraseñas o claves API, en los registros de producción. Loguru te permite controlar este comportamiento para diferentes entornos:
from loguru import logger
import os
# Development: Full diagnostic informationif os.getenv("ENVIRONMENT")=="development":
logger.add("app.log", diagnose=True, level="DEBUG")else:# Production: Basic logging without variable inspection
logger.add("app.log", diagnose=False, level="INFO")@logger.catchdefauthenticate_user(username, password, api_key):# In development, you'll see all variable values if this crashes# In production, sensitive data stays hiddenifnot username ornot password:raise ValueError("Missing credentials")Con la tecnología de
Evaluación perezosa para mejorar el rendimiento
Otra potente característica es la evaluación diferida, que mejora el rendimiento al registrar operaciones costosas. A veces quieres registrar información compleja, pero solo si realmente se produce un error:
from loguru import logger
@logger.catchdefprocess_large_dataset(data):try:# Some complex processing that might fail
result = complex_calculation(data)return result
except Exception as e:# This expensive operation only runs if there's an error
logger.error("Processing failed with data: {data}",
data=lambda: expensive_data_summary(data))raisedefexpensive_data_summary(data):# This function takes time to run, summarizing huge datasetsreturn{"row_count":len(data),"columns":list(data.keys()),"memory_usage": data.memory_usage()}Con la tecnología de
La sintaxis « lambda: » crea una función que solo se invoca cuando Loguru escribe realmente el mensaje de registro. Si no se produce ningún error, expensive_data_summary() nunca se ejecuta, lo que ahorra tiempo de procesamiento.
Diferentes estrategias para diferentes tipos de errores
También puedes utilizar diferentes estrategias de gestión de excepciones para diferentes tipos de errores:
from loguru import logger
# Configure multiple outputs for different error severities
logger.add("warnings.log", level="WARNING",filter=lambda record: record["level"].name =="WARNING")
logger.add("critical_errors.log", level="ERROR")@logger.catch(level="ERROR")defcritical_database_operation(query):# Database errors get logged as ERROR level
execute_database_query(query)@logger.catch(level="WARNING", reraise=False)defoptional_feature(user_id):# Non-critical features log as WARNING and continue execution
send_optional_notification(user_id)defprocess_user_request(user_id, query):# Critical operation - if this fails, the whole request fails
critical_database_operation(query)# Optional operation - if this fails, request continues
optional_feature(user_id)Con la tecnología de
El parámetro « reraise=False » indica a Loguru que registre la excepción, pero que no la vuelva a generar, lo que permite que el programa continúe. Esto resulta útil para funciones opcionales que no deben interrumpir el flujo de trabajo principal.
Ejemplo completo: procesamiento de archivos con gestión de errores
Veamos un ejemplo completo con un sistema de procesamiento de archivos que gestiona diferentes tipos de errores con elegancia:
from loguru import logger
import os
# Set up environment-aware loggingif os.getenv("DEBUG"):
logger.add("file_processor.log", diagnose=True, level="DEBUG")else:
logger.add("file_processor.log", diagnose=False, level="INFO")@logger.catch(reraise=False)defvalidate_file_format(filename):ifnot filename.endswith(('.csv','.json','.xml')):raise ValueError(f"Unsupported file format: {filename}")@logger.catchdefload_file_data(filename):
logger.info("Loading file: {}", filename)# Expensive operation only logged on errors
logger.debug("File stats: {stats}",
stats=lambda:{"size": os.path.getsize(filename),"modified": os.path.getmtime(filename)})withopen(filename,'r')as f:return f.read()defprocess_files(file_list):
results =[]for filename in file_list:# Validation errors are logged but don't stop processing
validate_file_format(filename)try:# Loading errors are logged and do stop processing this file
data = load_file_data(filename)
results.append(data)
logger.success("Successfully processed {}", filename)except Exception:
logger.error("Skipping file {} due to loading error", filename)continuereturn resultsCon la tecnología de
Esta configuración te ofrece captura automática de excepciones, contexto detallado de los errores cuando es necesario y diferentes estrategias de gestión para distintos tipos de errores. Tus registros se vuelven mucho más útiles para la depuración, mientras que tu código permanece limpio y legible.
Configuración y personalización avanzadas de Loguru
A medida que tus aplicaciones crezcan, te encontrarás con situaciones en las que los valores predeterminados de Loguru no se ajustan del todo a tus necesidades. Quizás necesites un nivel de registro especial para métricas empresariales, quieras filtrar datos confidenciales de los registros o necesites enviar alertas a Slack cuando se produzcan errores.
La buena noticia es que Loguru está diseñado para personalizarse sin perder su simplicidad. Puedes ampliarlo de formas que requerirían una configuración compleja en los sistemas de registro tradicionales, todo ello manteniendo tu código limpio y legible.
Veamos las personalizaciones más útiles que resuelven problemas reales a los que te enfrentarás en aplicaciones de producción.
Niveles y colores de registro personalizados
Loguru viene con niveles estándar como INFO, DEBUG y ERROR. Pero a veces necesitas algo específico para tu aplicación. Quizás quieras un nivel especial para métricas de rendimiento o eventos empresariales.
Crear niveles de registro personalizados es muy sencillo:
from loguru import logger
# Add a custom level for business metrics
logger.level("METRIC", no=38, color="<yellow>", icon="📊")# Add a custom level for security events
logger.level("SECURITY", no=45, color="<red><bold>", icon="🔒")# Now you can use these levels
logger.log("METRIC","Order completed in {} seconds",2.5)
logger.log("SECURITY","Failed login attempt from IP: {}","192.168.1.100")Con la tecnología de
El parámetro no establece la prioridad del nivel (cuanto mayor sea el número, mayor será la prioridad). Uso de los niveles estándar: DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50.
Veamos esto en un escenario de formación en machine learning:
from loguru import logger
# Set up custom levels for ML tracking
logger.level("EPOCH", no=35, color="<cyan><bold>")
logger.level("CHECKPOINT", no=38, color="<green><bold>")# Configure output
logger.remove()
logger.add("training_{time:YYYY-MM-DD}.log", level="INFO")deftrain_model(model, data_loader, epochs=10):
logger.info("Starting training with {} epochs", epochs)for epoch inrange(epochs):# Log epoch progress with custom level
logger.log("EPOCH","Epoch {}/{} started", epoch +1, epochs)# Training logic here
loss =0.523-(epoch *0.05)# Simulated improving loss
accuracy =0.72+(epoch *0.03)# Simulated improving accuracy
logger.info("Loss: {:.4f}, Accuracy: {:.2%}", loss, accuracy)# Save checkpoint every 5 epochsif(epoch +1)%5==0:
logger.log("CHECKPOINT","Model saved at epoch {}", epoch +1)
logger.success("Training completed!")Con la tecnología de
Interceptar y modificar mensajes de registro
A veces es necesario modificar los mensajes de registro antes de que se escriban. Algunos casos de uso habituales son eliminar datos confidenciales, añadir ID de solicitud o reformatear mensajes para herramientas específicas.
Loguru te permite interceptar mensajes utilizando el parámetrofilter:
from loguru import logger
import re
defhide_sensitive_data(record):# Hide credit card numbers
record["message"]= re.sub(r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b','XXXX-XXXX-XXXX-XXXX',
record["message"])# Hide email addresses
record["message"]= re.sub(r'\b[\w.-]+@[\w.-]+\.\w+\b','***@***.***',
record["message"])# Continue processing the logreturnTrue# Add the filter to your logger
logger.add("secure.log",filter=hide_sensitive_data)# Test it
logger.info("User paid with card 4532-1234-5678-9012")
logger.info("Contact email: [email protected]")Con la tecnología de
También puedes utilizar filtros para añadir información contextual:
from loguru import logger
import threading
defadd_thread_info(record):# Add thread name to every log message
record["extra"]["thread_name"]= threading.current_thread().name
returnTruedefadd_environment_info(record):# Add environment to production logs
record["extra"]["env"]="production"
record["extra"]["region"]="us-west-2"returnTrue# Apply multiple filters
logger.add("app.log",filter=lambda record: add_thread_info(record)and add_environment_info(record),format="{time} | {extra[env]} | {extra[thread_name]} | {message}")Con la tecnología de
Lavabos a medida para servicios externos
Un sumidero es el lugar al que fluyen tus registros. Aunque los archivos y la consola son comunes, a menudo es necesario enviar registros a servicios externos como Slack, correo electrónico o sistemas de supervisión.
A continuación se explica cómo crear un sumidero personalizado que envía los errores a Slack:
from loguru import logger
import requests
defsend_to_slack(message):"""Custom sink that sends messages to Slack"""# Parse the log record
record = message.record
# Only send errors and aboveif record["level"].no <40:# ERROR level is 40return# Format message for Slack
slack_message ={"text":f"🚨 {record['level'].name}: {record['message']}","attachments":[{"color":"danger","fields":[{"title":"Time","value":str(record["time"]),"short":True},{"title":"Function","value": record["function"],"short":True},{"title":"File","value":f"{record['file'].name}:{record['line']}","short":False}]}]}# Send to Slack webhook
webhook_url ="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
requests.post(webhook_url, json=slack_message)# Add the custom sink
logger.add(send_to_slack, level="ERROR")# Test it
logger.error("Database connection lost!")Con la tecnología de
Aquí tienes otro ejemplo práctico: un sumidero personalizado que recopila métricas de rendimiento durante la ejecución de la aplicación y las guarda para su análisis:
from loguru import logger
from collections import defaultdict
import json
classMetricsCollector:def__init__(self):
self.metrics = defaultdict(list)def__call__(self, message):"""This method is called for every log message"""
record = message.record
# Only process METRIC level logsif record["level"].name !="METRIC":return# Extract metric data from the 'extra' fields
extra = record["extra"]if"metric_name"in extra and"value"in extra:
self.metrics[extra["metric_name"]].append({"value": extra["value"],"timestamp": record["time"].timestamp()})defsave_metrics(self):"""Save all collected metrics to a JSON file"""withopen("metrics.json","w")as f:
json.dump(dict(self.metrics), f, indent=2)# Create the collector and add it as a sink
collector = MetricsCollector()
logger.add(collector)# Create the METRIC level
logger.level("METRIC", no=38)# Now when you log metrics, they're automatically collected# The bind() method attaches extra data to the log entry
logger.bind(metric_name="response_time", value=0.234).log("METRIC","API response")
logger.bind(metric_name="response_time", value=0.189).log("METRIC","API response")
logger.bind(metric_name="active_users", value=1523).log("METRIC","User count")# Later, save all metrics to file
collector.save_metrics()# The metrics.json file will contain:# {# "response_time": [# {"value": 0.234, "timestamp": 1627...},# {"value": 0.189, "timestamp": 1627...}# ],# "active_users": [# {"value": 1523, "timestamp": 1627...}# ]# }Con la tecnología de
La ventaja de este enfoque es que el código de la aplicación permanece limpio: solo tienes que registrar las métricas como de costumbre y el colector se encarga automáticamente del almacenamiento. Puedes sustituirlo fácilmente por un sumidero que envíe métricas a Prometheus, DataDog o cualquier otro servicio de monitorización.
Estas personalizaciones te ofrecen la flexibilidad necesaria para adaptar Loguru a tus necesidades específicas sin perder la simplicidad que lo hace tan especial. Tanto si estás creando un pequeño script como una gran aplicación, puedes ampliar Loguru para que se adapte a tus necesidades específicas de registro sin necesidad de archivos de configuración complejos ni código repetitivo.
Conclusión
Loguru hace que el registro en Python sea tan sencillo como debería ser. Se acabaron los archivos de configuración, la configuración de controladores y el código repetitivo. Solo tienes que importar y empezar a registrar con colores, marcas de tiempo y rotación automática de archivos.
Ya has visto cómo gestiona los puntos débiles más comunes: guardar registros en archivos, rotarlos automáticamente, capturar excepciones con todo el contexto y enviar registros a servicios externos. Las funciones de registro estructurado lo hacen apto para la producción, mientras que los niveles y sumideros personalizados te permiten adaptarlo a cualquier caso de uso.
Utiliza Loguru cuando:
Estás cansado de depurar impresiones
Necesitas scripts o cuadernos de registro rápido.
Estás creando aplicaciones web que necesitan registros estructurados.
Deseas un mejor seguimiento de las excepciones sin una configuración compleja.
Empieza poco a poco. Reemplaza una instrucción de impresión por logger.info(). Nunca volverás atrás.
Preguntas frecuentes sobre Loguru
¿En qué se diferencia Loguru de otras bibliotecas de registro de Python?⌄
Loguru destaca por no requerir ninguna configuración: puedes empezar a registrar inmediatamente con from loguru import logger. A diferencia del módulo de registro integrado de Python, que necesita controladores, formateadores y una configuración compleja, Loguru proporciona colores, marcas de tiempo y rotación de archivos desde el primer momento. También ofrece un seguimiento mejorado con inspección variable que otras bibliotecas no proporcionan.
¿Cuáles son las principales ventajas de utilizar Loguru en lugar del módulo de registro integrado en Python?⌄
Loguru elimina la complejidad de la configuración, proporciona rotación y retención automática de archivos, ofrece registros JSON estructurados con serialize=True, incluye seguimiento de excepciones mejorado con valores variables y admite sumideros personalizados para servicios externos. Obtienes funciones de registro listas para la producción sin necesidad de escribir código de configuración.
¿Loguru puede gestionar aplicaciones multihilo de manera eficiente?⌄
Sí, Loguru es seguro para subprocesos de forma predeterminada y gestiona bien las aplicaciones multihilo. Puedes añadir información sobre subprocesos a los registros utilizando filtros, y el método logger.bind() funciona en todos los subprocesos para mantener el contexto. El rendimiento de Loguru está optimizado para el registro simultáneo sin bloquear subprocesos.
¿Cómo funciona la rotación y retención automática de registros de Loguru?⌄
Loguru ofrece una rotación flexible basada en el tamaño del archivo (rotación = «10 MB»), intervalos de tiempo (rotación = «00:00» para diaria) o condiciones personalizadas. La retención elimina automáticamente los archivos antiguos (retención=10 conserva 10 archivos) y la compresión ahorra espacio (compresión="zip"). Todo se realiza automáticamente sin necesidad de gestionar archivos manualmente.
¿Cuáles son algunos ejemplos prácticos del uso de las funciones personalizadas de Loguru?⌄
Los sumideros personalizados te permiten enviar registros a servicios externos como Slack para alertas de errores, recopilar métricas para sistemas de supervisión o dar formato a los registros para herramientas específicas. Puedes crear sumideros que filtren por nivel de registro, añadir información contextual o integrarlos con servicios como DataDog, Prometheus o notificaciones por correo electrónico para errores críticos.
Aprende sobre la regresión logística, sus propiedades básicas, y construye un modelo de machine learning sobre una aplicación del mundo real en Python.
Esta guía completa te enseña los fundamentos del backend con Python. Aprende conceptos básicos, frameworks y buenas prácticas para empezar a crear aplicaciones web.
Aprende Python para el desarrollo de software, desde escribir funciones hasta definir clases. Adquiere las habilidades necesarias para arrancar tu carrera como desarrollador.
Has estado depurando con instrucciones «
print()» durante toda tu vida como programador. Quizás hayas probado el módulo de registro de Python una o dos veces, pero hayas vuelto a los prints porque son más sencillos.En realidad, hay algo mejor que es igual de fácil de usar.
Las declaraciones de impresión no se pueden guardar en archivos ni activar y desactivar fácilmente. El registro integrado de Python puede hacer estas cosas, pero requiere escribir código de configuración más largo que tu programa real.
Loguru adopta un enfoque diferente: el registro debe ser tan fácil como imprimir, pero mucho más útil. Obtienes colores en tu terminal, marcas de tiempo automáticas y la posibilidad de guardar todo en archivos sin escribir una sola línea de configuración.
En este tutorial, te mostraré ejemplos prácticos que hacen que el registro sea algo natural en lugar de una tarea pesada. Descubrirás funciones que probablemente no conocías, utilizando patrones de código que facilitan la depuración.
Si eres nuevo en la depuración de Python o deseas reforzar tus habilidades básicas, adquirir unos fundamentos sólidos de Python te ayudará a comprender cuándo y por qué es necesario el registro.
Primeros pasos con Loguru: Magia sin configuración
Para instalar Loguru solo hay que ejecutar un comando:
Con el módulo
loggingnormal, tendrías que configurar controladores, formateadores y todo lo demás antes de ver un solo mensaje de registro.Para una comparación más detallada de los métodos de registro integrados en Python, consulta este tutorial completo sobre registro que cubre los métodos tradicionales.
Con Loguru, solo tienes que importar y empezar a registrar:
La salida aparece en tu terminal con colores, marcas de tiempo y niveles de registro automáticamente. No requiere configuración.
Supongamos que estás creando un sencillo rastreador web. Así es como cambia la depuración:
Observa los diferentes niveles de registro (
info,debug,success,error) y el formato con llaves. Todo funciona inmediatamente sin archivos de configuración ni código de instalación.Registro y rotación de archivos simplificados
Cuando depuras con la salida de la consola, pierdes todo en el momento en que cierras el terminal. No puedes buscar lo que ocurrió hace una hora y, si tu script se bloquea durante la noche, no hay rastro de lo que ha fallado. Tampoco puedes compartir fácilmente los resultados de la depuración con tus compañeros de equipo cuando solicitas ayuda.
El registro de archivos resuelve este problema guardando todo de forma permanente.
El registro tradicional te obliga a escribir código de configuración para configurar los controladores de archivos. Debes especificar las rutas de los archivos, crear directorios y gestionar los permisos. Con Loguru, añadir el registro de archivos es, literalmente, una línea:
Ahora todo se guarda en
app.logy sigue apareciendo en tu terminal.Pero los archivos de registro se vuelven enormes con el tiempo. Una aplicación web que se ejecuta durante días puede generar gigabytes de registros que, con el tiempo, llenarán tu disco. La rotación de archivos resuelve este problema creando automáticamente nuevos archivos de registro cuando se cumplen determinadas condiciones. El archivo antiguo se renombra con una marca de tiempo y se crea un archivo nuevo:
Las marcas de tiempo predeterminadas funcionan, pero a menudo están en UTC o son difíciles de leer. Loguru te permite personalizar los formatos de fecha y hora según tus necesidades:
Para los sistemas de producción, necesitas un mayor control sobre los archivos antiguos. El registro de producción requiere seguir las prácticas recomendadas de Python para garantizar que tus registros sean mantenibles y seguros. Sin gestión, los archivos de registro se acumulan y consumen almacenamiento:
Veamos esto en un escenario realista. Estás creando un canal de datos que procesa varios archivos CSV cada noche, limpiando y validando los datos de los clientes antes de cargarlos en tu base de datos. Debes realizar un seguimiento de los archivos que se han procesado correctamente y detectar cualquier problema de calidad de los datos:
Tus registros se guardan con marcas de tiempo legibles, los archivos se rotan automáticamente y los registros antiguos se limpian solos. Puedes revisar lo que sucedió días después o enviar archivos de registro a tus compañeros de trabajo cuando solucionen problemas.
Registro estructurado para aplicaciones modernas
Cuando ejecutas una aplicación web, tus registros se convierten rápidamente en un caos de información mezclada. Las acciones de los usuarios, las consultas a la base de datos, las llamadas a la API y los errores se mezclan en un muro de texto. No puedes filtrar fácilmente por usuarios específicos, rastrear solicitudes individuales ni analizar automáticamente registros para sistemas de supervisión.
Las aplicaciones basadas en datos se benefician especialmente del registro estructurado. Si trabajas con canalizaciones de datos o análisis, desarrollar habilidades de analista de datos te ayudará a comprender qué información debes capturar en tus registros.
El registro tradicional basado en cadenas empeora aún más la situación. Todos los mensajes de registro son solo texto, por lo que extraer datos significativos requiere patrones de expresiones regulares complejos o búsquedas manuales.
El registro estructurado cambia esto al tratar las entradas de registro como objetos de datos en lugar de solo texto. Cada entrada del registro se convierte en un registro estructurado con campos que se pueden buscar, lo que facilita la consulta y el análisis mediante programación.
Registro estructurado JSON con serialize=True
Loguru simplifica el registro estructurado con la opción «
serialize=True» (Registro estructurado):El parámetro «
serialize=True» indica a Loguru que genere JSON en lugar de texto sin formato. En lugar de frases legibles, tu archivo de registro ahora contiene datos estructurados:Este formato funciona perfectamente con herramientas de análisis de registros que pueden buscar y filtrar datos JSON automáticamente.
Enlace de contexto
Pero las aplicaciones web necesitan algo más que datos estructurados. Necesitas contexto que conecte las entradas de registro relacionadas. Al procesar una solicitud de usuario, es conveniente que todos los registros relacionados compartan información común, como el ID de usuario o el ID de sesión.
El enlace de contexto resuelve esto adjuntando información persistente a tu registrador mediante
logger.bind():Ahora, todos los registros de
order_loggerincluyen automáticamenteuser_idyorder_id, lo que facilita el seguimiento de todos los registros relacionados con un pedido específico.Múltiples sumideros para diferentes salidas
Las aplicaciones modernas también necesitan diferentes salidas de registro para diferentes fines. Es posible que desees registros de consola legibles durante el desarrollo, pero registros JSON para la supervisión de la producción. En Loguru, cada destino de salida se denomina «sumidero», es decir, un lugar al que fluyen los mensajes de registro.
Loguru te permite añadir múltiples sumideros con diferentes formatos y reglas:
La llamada
logger.remove()elimina la salida predeterminada de la consola de Loguru para que puedas configurar la tuya propia. Cadalogger.add()crea un nuevo sumidero con sus propias reglas sobre lo que se registra y cómo se formatea.Ahora las mismas sentencias de registro producen resultados diferentes:
Ejemplo completo de Loguru: Sistema de registro de usuarios
Veamos esto con un ejemplo más sencillo y realista del uso de Loguru: un sistema básico de registro de usuarios.
Esta configuración te proporciona una salida de consola legible durante el desarrollo, registros JSON estructurados para la supervisión automatizada y registros de errores independientes para las alertas. El método `
bind()` garantiza que todos los registros de cada registro de usuario incluyan la dirección de correo electrónico, lo que facilita enormemente la depuración.Gestión de excepciones Loguru
Cuando tu código falla, normalmente obtienes un seguimiento básico de la pila que te indica dónde se ha producido el error, pero no te da mucha información sobre el motivo. Pierdes los valores de las variables en el momento del bloqueo, lo que dificulta comprender qué ha fallado. El manejo tradicional de excepciones también requiere que envuelvas todo en bloques try-catch y registres manualmente cada excepción.
Esto resulta especialmente doloroso cuando se depuran problemas de producción. Los usuarios informan de errores, pero tú no puedes reproducirlos porque no conoces el contexto en el que se produjeron.
Loguru resuelve esto con la captura automática de excepciones y trazas mejoradas que te muestran exactamente qué estaba sucediendo en tu código cuando surgieron los problemas.
Captura automática de excepciones con @logger.catch
El decorador `
@logger.catch` captura automáticamente cualquier excepción que se produzca en una función y la registra con todo el contexto. Los decoradores como@logger.catchson un concepto intermedio de Python que puede transformar la forma en que gestionas los errores en tu código base:En lugar de que tu programa se bloquee con un mensaje de error básico, Loguru captura la excepción y la registra con información detallada, mientras tu programa sigue ejecutándose. El decorador funciona en cualquier función: métodos de clase, funciones asíncronas o funciones normales.
Rastreos mejorados con inspección de variables
Pero Loguru va más allá con trazas mejoradas que muestran los valores de las variables en cada nivel de la pila de llamadas. Esta función se llama «diagnóstico» y es como tener un depurador integrado en tus registros:
Con «
diagnose=True», cuando la función se bloquea al intentar restar una cadena de un número, Loguru te muestra exactamente qué había en cada variable:Este nivel de detalle agiliza considerablemente la depuración, ya que permite ver exactamente qué datos han causado el problema.
Gestión de excepciones respetuosa con el medio ambiente
Sin embargo, los rastreos mejorados pueden exponer información confidencial, como contraseñas o claves API, en los registros de producción. Loguru te permite controlar este comportamiento para diferentes entornos:
Evaluación perezosa para mejorar el rendimiento
Otra potente característica es la evaluación diferida, que mejora el rendimiento al registrar operaciones costosas. A veces quieres registrar información compleja, pero solo si realmente se produce un error:
La sintaxis «
lambda:» crea una función que solo se invoca cuando Loguru escribe realmente el mensaje de registro. Si no se produce ningún error,expensive_data_summary()nunca se ejecuta, lo que ahorra tiempo de procesamiento.Diferentes estrategias para diferentes tipos de errores
También puedes utilizar diferentes estrategias de gestión de excepciones para diferentes tipos de errores:
El parámetro «
reraise=False» indica a Loguru que registre la excepción, pero que no la vuelva a generar, lo que permite que el programa continúe. Esto resulta útil para funciones opcionales que no deben interrumpir el flujo de trabajo principal.Ejemplo completo: procesamiento de archivos con gestión de errores
Veamos un ejemplo completo con un sistema de procesamiento de archivos que gestiona diferentes tipos de errores con elegancia:
Esta configuración te ofrece captura automática de excepciones, contexto detallado de los errores cuando es necesario y diferentes estrategias de gestión para distintos tipos de errores. Tus registros se vuelven mucho más útiles para la depuración, mientras que tu código permanece limpio y legible.
Configuración y personalización avanzadas de Loguru
A medida que tus aplicaciones crezcan, te encontrarás con situaciones en las que los valores predeterminados de Loguru no se ajustan del todo a tus necesidades. Quizás necesites un nivel de registro especial para métricas empresariales, quieras filtrar datos confidenciales de los registros o necesites enviar alertas a Slack cuando se produzcan errores.
La buena noticia es que Loguru está diseñado para personalizarse sin perder su simplicidad. Puedes ampliarlo de formas que requerirían una configuración compleja en los sistemas de registro tradicionales, todo ello manteniendo tu código limpio y legible.
Veamos las personalizaciones más útiles que resuelven problemas reales a los que te enfrentarás en aplicaciones de producción.
Niveles y colores de registro personalizados
Loguru viene con niveles estándar como INFO, DEBUG y ERROR. Pero a veces necesitas algo específico para tu aplicación. Quizás quieras un nivel especial para métricas de rendimiento o eventos empresariales.
Crear niveles de registro personalizados es muy sencillo:
El parámetro
noestablece la prioridad del nivel (cuanto mayor sea el número, mayor será la prioridad). Uso de los niveles estándar: DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50.Veamos esto en un escenario de formación en machine learning:
Interceptar y modificar mensajes de registro
A veces es necesario modificar los mensajes de registro antes de que se escriban. Algunos casos de uso habituales son eliminar datos confidenciales, añadir ID de solicitud o reformatear mensajes para herramientas específicas.
Loguru te permite interceptar mensajes utilizando el parámetro
filter:También puedes utilizar filtros para añadir información contextual:
Lavabos a medida para servicios externos
Un sumidero es el lugar al que fluyen tus registros. Aunque los archivos y la consola son comunes, a menudo es necesario enviar registros a servicios externos como Slack, correo electrónico o sistemas de supervisión.
A continuación se explica cómo crear un sumidero personalizado que envía los errores a Slack:
Aquí tienes otro ejemplo práctico: un sumidero personalizado que recopila métricas de rendimiento durante la ejecución de la aplicación y las guarda para su análisis:
La ventaja de este enfoque es que el código de la aplicación permanece limpio: solo tienes que registrar las métricas como de costumbre y el colector se encarga automáticamente del almacenamiento. Puedes sustituirlo fácilmente por un sumidero que envíe métricas a Prometheus, DataDog o cualquier otro servicio de monitorización.
Estas personalizaciones te ofrecen la flexibilidad necesaria para adaptar Loguru a tus necesidades específicas sin perder la simplicidad que lo hace tan especial. Tanto si estás creando un pequeño script como una gran aplicación, puedes ampliar Loguru para que se adapte a tus necesidades específicas de registro sin necesidad de archivos de configuración complejos ni código repetitivo.
Conclusión
Loguru hace que el registro en Python sea tan sencillo como debería ser. Se acabaron los archivos de configuración, la configuración de controladores y el código repetitivo. Solo tienes que importar y empezar a registrar con colores, marcas de tiempo y rotación automática de archivos.
Ya has visto cómo gestiona los puntos débiles más comunes: guardar registros en archivos, rotarlos automáticamente, capturar excepciones con todo el contexto y enviar registros a servicios externos. Las funciones de registro estructurado lo hacen apto para la producción, mientras que los niveles y sumideros personalizados te permiten adaptarlo a cualquier caso de uso.
Utiliza Loguru cuando:
Para obtener más información, consulta la documentación oficial junto con este tutorial sobre registro para obtener una descripción completa de las estrategias de registro de Python.
Empieza poco a poco. Reemplaza una instrucción de impresión por
logger.info(). Nunca volverás atrás.