Registry / observability / loguru

loguru

JSON →
library0.7.3pypypi✓ verified 26d ago

Simple Python logging library. Current version: 0.7.3 (Mar 2026). One global logger — no instantiation needed, just import. Default sink is stderr (not stdout). diagnose=True is the DEFAULT — shows variable values in tracebacks — leaks sensitive data in production. Must call logger.remove() before reconfiguring. Library authors must never call logger.add() — use logger.disable() instead. enqueue=True requires logger.complete() on shutdown to flush queued messages.

pip install loguru
INSTALL
IMPORT
SIG · LOGURU
L
loguru
observabilitypythonv0.7.3
Install
1.7s avg
Import
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.7.3 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.000s · 18.2MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.7s · import 0.000s · 19MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

basic usage + reconfigure
import sys from loguru import logger # Remove default stderr handler before reconfiguring logger.remove() # Add stdout handler with INFO level logger.add( sys.stdout, level='INFO', format='{time:YYYY-MM-DD HH:mm:ss} | {level} | {name}:{line} | {message}', diagnose=False, # IMPORTANT: disable in production — prevents variable leak backtrace=True ) # Add file sink with rotation logger.add( 'logs/app.log', level='DEBUG', rotation='10 MB', retention='7 days', compression='zip', diagnose=False, serialize=False ) logger.info('App started') logger.debug('Debug message') logger.warning('Watch out') # Exception catching try: 1 / 0 except Exception: logger.exception('Division failed')
from loguru import logger # Wrong: adding new sink without removing default # Now logs go to BOTH stderr AND your new sink logger.add('app.log') # default stderr sink still active # Wrong: diagnose=True (default) in production leaks variable values logger.add('prod.log', diagnose=True) # exposes sensitive data in tracebacks
Default handler (id=0) outputs to stderr. Call logger.remove() or logger.remove(0) before adding sinks to avoid duplicate output. diagnose=True is the default — always set diagnose=False in production.
library usage
# In a library — NEVER call logger.add() from loguru import logger # Disable by default — let app developer enable if they want logger.disable(__name__) def my_library_function(): logger.debug('Library internal log') # no-op unless enabled by app
# Wrong in a library — forces logging config on app developer from loguru import logger logger.add('library.log') # pollutes app's logging
Libraries must call logger.disable(__name__) and never call logger.add(). Application code enables library logging with logger.enable('library_name') if desired.

Loguru — reconfigure, file rotation, exception catching, structured context.

# pip install loguru import sys from loguru import logger # Reconfigure: remove default stderr, add stdout + file logger.remove() logger.add(sys.stdout, level='INFO', diagnose=False) logger.add('app.log', level='DEBUG', rotation='50 MB', diagnose=False) # Basic logging logger.debug('Debug message') logger.info('Server started on port 8000') logger.warning('Low disk space') logger.error('Connection failed') logger.critical('Database unreachable') # Exception logging with full traceback try: result = 1 / 0 except ZeroDivisionError: logger.exception('Calculation failed') # logs traceback automatically # Catch decorator @logger.catch def risky_function(x): return 100 / x risky_function(0) # caught and logged automatically # Structured context with bind() request_logger = logger.bind(request_id='req-123', user_id='usr-456') request_logger.info('Processing payment') # JSON output for log aggregators logger.add('app.json', serialize=True, diagnose=False) # Async / multiprocess safe logger.add('async.log', enqueue=True, diagnose=False) # On shutdown: import asyncio asyncio.run(logger.complete()) # flush queued messages
Debug
Known issues
breakingdiagnose=True is the DEFAULT for all sinks. It displays variable values in exception tracebacks — leaks passwords, tokens, PII in production logs.
fix
Always set diagnose=False in production: logger.add('prod.log', diagnose=False)
affects: all
gotchaDefault sink outputs to stderr, not stdout. Many developers expect stdout. Adding a new sink without calling logger.remove() causes duplicate log output.
fix
Call logger.remove() before logger.add() to remove the default stderr handler.
affects: all
gotchaLibrary authors must never call logger.add(). Call logger.disable(__name__) instead. Calling add() in a library forces logging config on every downstream application.
fix
In library code: logger.disable(__name__). In app code: logger.enable('library_name') to see library logs.
affects: all
gotchaenqueue=True (multiprocess/async safe) requires logger.complete() on shutdown. Without it, buffered messages in the queue are lost when the process exits.
fix
await logger.complete() in async code, or asyncio.run(logger.complete()) at shutdown.
affects: all
gotchaPassing integer log levels to logger.log() displays as anonymous level ('Level 20') instead of level name. Loguru identifies levels by name, not number.
fix
Use string names: logger.log('INFO', 'message') not logger.log(20, 'message')
affects: all
gotchalogger.add() returns a handler ID integer. logger.remove() requires this ID to remove a specific handler. Calling logger.remove() with no args removes ALL handlers.
fix
handler_id = logger.add(...); logger.remove(handler_id) to remove specific sink.
affects: all
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'loguru'
The Loguru library has not been installed in the active Python environment.
fix
Run `pip install loguru` in your terminal.
Sensitive data leakage in production logs due to diagnose=True
The default `diagnose=True` parameter for sinks in Loguru includes local variable values in exception tracebacks, which can expose sensitive information in production environments.
fix
Explicitly set `diagnose=False` when adding sinks in production: `logger.add('file.log', diagnose=False)`.
Logs are duplicated
The logger is being configured multiple times by repeatedly calling `logger.add()` without first calling `logger.remove()`, or by running configuration code in a multiprocessing environment without proper `if __name__ == '__main__':` guards.
fix
Call `logger.remove()` (optionally with the handler ID, e.g., `logger.remove(0)` for the default handler) before `logger.add()` to prevent duplicate handlers. For multiprocessing, wrap logger configuration in `if __name__ == '__main__':`.
KeyError: 'some_key' or ValueError: Single '{' encountered in format string when logging f-strings
Loguru's message formatting uses `str.format()` semantics for positional and keyword arguments, which can conflict with f-strings that contain unescaped curly braces not intended as format placeholders.
fix
Escape literal curly braces in f-strings with double braces (`{{` and `}}`) or pass the data as separate arguments to Loguru's logging methods if they are intended for structured logging.
ValueError: I/O operation error on closed file
Another library, IDE, or environment tool has replaced or closed `sys.stderr` or `sys.stdout` while Loguru was still attempting to write to it.
fix
Configure Loguru to use a lambda function as the sink to dynamically retrieve `sys.stderr` or `sys.stdout` (e.g., `logger.add(lambda m: sys.stderr.write(m))`), or ensure the logger is re-initialized if the standard streams might be replaced.
Upgrade
Version history
0.7.3latest on PyPI · released Dec 6, 2024
Audit
Dependencies

No dependency data recorded yet.

Agent activity
26 hits · last 30 days
node
20
OpenAI (training)
2
Resources
loguru — pip install loguru · libregistry