Back to Blog
Python

Loguru vs Standard Logging in Python

python loguru vs standard logging: Compare Python's standard logging module with Loguru: configuration, formatting, exception handling, performance, and when to choose...

PythonLoguruLoggingStandard LibraryDeveloper Tools
Side-by-side comparison of Python's standard logging module and the Loguru library, showing configuration code and log output.

When you need to add logging to a Python application, the standard library's logging module is the default choice. But Loguru, a third-party library, has gained traction by simplifying configuration and providing a more ergonomic API. This article compares python loguru vs standard logging in practical terms: setup, formatting, exception handling, filtering, performance, and the conditions that should drive your choice.

Configuration Differences at a Glance

The most visible difference is how much code it takes to get a working logger. With the standard library, you typically configure a logger, a handler, and a formatter separately:

import logging logger = logging.getLogger(__name__) handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) logger.setLevel(logging.INFO)

Loguru collapses this into a single line:

from loguru import logger logger.add("file.log", level="INFO")

Loguru automatically sends output to stderr by default and uses a pre-configured formatter that includes time, level, and message. The add() method accepts a sink (a file path, file object, or callable) and optional parameters for rotation, retention, and compression. The standard library requires you to build this pipeline manually, which is more verbose but also more explicit.

Formatting and Message Injection

Standard logging uses %-style formatting by default, though you can pass arguments to logger.info() to defer interpolation:

logger.info("User %s logged in from %s", user.name, request.ip)

Loguru uses braces and supports keyword arguments directly:

logger.info("User {name} logged in from {ip}", name=user.name, ip=request.ip)

Loguru also allows you to modify the format globally by passing a format string to logger.add(). For example, to include the function name and line number:

logger.add("app.log", format="{time} | {level} | {function}:{line} | {message}")

The standard library requires a Formatter with a similar format string, but you must attach it to each handler. Loguru's format string uses {time}, {level}, {message}, and other fields directly, which is more concise.

Exception Handling and Tracebacks

Capturing exceptions with the standard library usually means using logger.exception() inside an except block:

try: risky_operation() except Exception: logger.exception("Operation failed")

Loguru provides a decorator that automatically logs exceptions from any function:

from loguru import logger @logger.catch def risky_operation(): raise ValueError("boom")

When the decorated function raises, Loguru logs the full traceback with the exception message and then re-raises the exception. This is useful for top-level entry points where you want to ensure no exception goes unnoticed. The standard library has no equivalent; you must wrap each call site or rely on sys.excepthook.

Log Levels and Filtering

Both libraries support the standard levels: DEBUG, INFO, WARNING, ERROR, and CRITICAL. The standard library uses integer constants and a setLevel() method on loggers and handlers. Loguru uses string names in logger.add() and also allows custom levels via logger.level().

Filtering in the standard library is done with a Filter object or a function attached to a handler. Loguru accepts a filter parameter in logger.add() that can be a callable or a string with a level name. For example, to route warnings to a separate file:

logger.add("warnings.log", level="WARNING", filter=lambda record: record["level"].name == "WARNING")

Loguru's filter receives a record dict, giving you access to all log attributes. The standard library's filter receives a LogRecord object with similar fields, but the setup is more verbose.

Performance and Overhead

Performance is a common concern when comparing python loguru vs standard logging. Loguru's dynamic formatting and per-call overhead are generally higher than the standard library's optimized path. However, the difference is usually negligible for typical application workloads unless you are logging at a very high rate (e.g., in a tight loop).

The standard library is designed to be fast: it avoids formatting when the log level is disabled and uses lazy argument evaluation. Loguru also checks the level before formatting, but its use of **kwargs and dynamic record construction adds some overhead.

If you are logging thousands of messages per second, the standard library is likely the safer choice. For most applications, the convenience of Loguru outweighs the small performance cost. You can mitigate Loguru's overhead by using logger.opt(lazy=True) to defer argument evaluation, but that adds complexity.

Production Considerations and Maintainability

In production, you often need rotation, retention, and structured output. The standard library requires third-party handlers like TimedRotatingFileHandler or logging.handlers.WatchedFileHandler. Loguru has rotation and retention built into logger.add():

logger.add("app.log", rotation="500 MB", retention="10 days", compression="zip") ```n This is a major convenience for long-running services. Loguru also supports JSON serialization via a custom sink, but the standard library can achieve the same with a custom formatter. Maintainability depends on your team's familiarity. The standard library is guaranteed to be available, while Loguru is an external dependency. If you are building a library that others will import, using the standard library avoids imposing a dependency. For an application where you control the environment, Loguru's simpler API reduces boilerplate and makes logging code easier to read. ## Decision Criteria: When to Choose Which Use the standard library when: - You are writing a reusable library or package that should not force a third-party dependency on users. - You need fine-grained control over handlers, formatters, and filters and are comfortable with the verbosity. - You are working in an environment where adding dependencies is restricted or reviewed heavily. - You require the lowest possible logging overhead in a high-throughput service. Choose Loguru when: - You want to add logging to a script or application quickly without configuring handlers and formatters. - You value automatic exception capture via the `@logger.catch` decorator. - You need built-in rotation and retention without wiring up extra handlers. - Your team prefers a more concise, readable logging API. Both tools are capable of producing production-grade logs. The decision is primarily about tradeoffs: the standard library offers control and zero dependencies, while Loguru offers speed of development and a more ergonomic interface. If you are starting a new application and are not constrained by dependencies, Loguru can reduce the initial friction. If you are building a library that others will consume, stick with the standard library to avoid forcing your logging choice on downstream users.
python loguru vs standard logging: Practical Usage and Code | RYUSLOG DEV