Simplify Python Logging with Loguru: One‑Line Configuration
This article explains why traditional Python logging is cumbersome, demonstrates the verbose boilerplate required, and then shows how the Loguru library can replace it with a minimal, powerful setup that includes automatic exception handling, colored output, log rotation, async support, and structured logging for both web and script applications.
Why Python logging feels painful
Configuring the built‑in logging module often requires many lines of boilerplate code—handlers, formatters, level settings, and file rotation—making the setup feel like assembling IKEA furniture without instructions.
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger('MyApp')
handler = logging.StreamHandler()
file_handler = RotatingFileHandler('app.log', maxBytes=5*1024*1024, backupCount=10)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(file_handler)
logger.setLevel(logging.DEBUG)Such code is repetitive, error‑prone, and produces cryptic error messages when a handler or formatter is omitted, while log levels (DEBUG, INFO, WARNING, ERROR, CRITICAL) are often misunderstood.
Loguru: the rescue tool
Loguru is a third‑party library that makes logging in Python exceptionally simple.
Minimal configuration
from loguru import logger
logger.add("logs/app.log", level="DEBUG", format="{time:YYYY-MM-DD HH:mm:ss} - {level} - {file} - {line} - {message}", rotation="10 MB")
logger.info('Can write logs now')With a single logger.add call you get file creation, rotation, level filtering, and a readable format; no manual handler or formatter setup is needed.
Why Loguru feels like a savior
Out‑of‑the‑box : import and start logging immediately, and the same logger works across all modules.
Powerful features : automatic log rotation, exception capture via @logger.catch, colored console output, async‑safe logging, and structured key‑value logging.
Structured logging :
logger.info("User action", user_id=123, action="login", success=True)Using Loguru in real projects
Web development with FastAPI
from fastapi import FastAPI
from loguru import logger
app = FastAPI()
@app.middleware("http")
async def log_requests(request, call_next):
logger.info(f"Request: {request.method} {request.url}")
response = await call_next(request)
logger.info(f"Response: {response.status_code}")
return response
@app.get("/")
async def read_root():
logger.info("Access root path")
return {"Hello": "World"}Data‑processing progress tracking
from loguru import logger
def process_data(data):
total = len(data)
for i, item in enumerate(data):
# process item ...
if i % 100 == 0:
logger.info(f"Progress: {i}/{total} ({i/total*100:.1f}%)")
logger.debug(f"Processing item: {item}")
logger.success(f"Data processing completed, {total} records processed")Script debugging with automatic exception capture
from loguru import logger
@logger.catch
def main():
logger.info("Script start")
# your code here
logger.info("Script finished")
if __name__ == "__main__":
main()When Loguru cannot be used: a reusable logging helper
If project constraints require the standard logging module, you can wrap the boilerplate in a function:
import logging, os
def setup_logger(name=None, level=logging.INFO):
"""Create and return a configured logger instance"""
logger = logging.getLogger(name or __name__)
logger.setLevel(level)
if not logger.handlers:
console_handler = logging.StreamHandler()
console_handler.setLevel(level)
os.makedirs('logs', exist_ok=True)
file_handler = logging.handlers.RotatingFileHandler('logs/app.log', maxBytes=5*1024*1024, backupCount=3, encoding='utf-8')
file_handler.setLevel(level)
formatter = logging.Formatter('%(asctime)s - [%(levelname)s] - %(name)s - %(filename)s:%(lineno)d - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
return logger
logger = setup_logger('my_app')
logger.info('Logging is now simple')Best practices for logging
1. Choose appropriate log levels
DEBUG : detailed debugging information, for development.
INFO : confirm normal operation.
WARNING : indicate a potential problem.
ERROR : a serious issue that prevents part of the program from working.
CRITICAL : a fatal error that stops the program.
2. Include context information
# Bad practice
logger.error("Operation failed")
# Good practice
logger.error("User operation failed", user_id=user_id, action=action, reason=error_msg)3. Consider performance in production
# Avoid expensive string formatting in tight loops
if logger.isEnabledFor(logging.DEBUG):
expensive_data = generate_expensive_debug_data()
logger.debug("Data: %s", expensive_data)Conclusion
By adopting Loguru or a well‑encapsulated wrapper around the standard logging module, Python developers can turn chaotic logging into a clear, maintainable, and performant practice—much like a flight recorder that helps pinpoint issues quickly.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
IT Services Circle
Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
