Python自身具有默认的日志组件-loggin,功能强大且专业度强,正因如此,要真正的用好logging组件的复杂度可不低。你是否曾因懒配置logging组件而只是对其简单配置一下或直接使用 print()
?……我曾有过,但日志记录是每个应用的基础,能极大简化调试过程。然而,可以通过 Loguru组件来极度轻松的使用日志,你没有任何理由不从项目伊始就使用它——只需 from loguru import logger
即可开始,简单至极。
此外,该库通过添加一系列实用功能解决标准日志模块的痛点,力求让 Python 日志记录不再痛苦。日志记录应成为开发的本能,而 Loguru 试图使其既愉悦又强大。
pip install loguru
开箱即用,无需样板代码
无需配置 Handler
、Formatter
、Filter
,一个函数搞定一切。
更便捷的文件日志管理
支持日志轮转(rotation)、保留(retention)和压缩(compression)。
现代大括号风格字符串格式化
类似 str.format()
,更优雅强大。
自动捕获主线程或子线程异常
确保所有错误都能记录。
美观的彩色日志输出
终端兼容时自动着色。
异步、线程安全、多进程安全
默认线程安全,支持消息入队确保多进程安全。
完整的异常描述
显示变量值和完整堆栈跟踪(生产环境需谨慎启用)。
按需结构化日志
支持序列化为 JSON。
惰性求值优化性能
避免生产环境中不必要的计算开销。
自定义日志级别
灵活添加新级别并设置颜色和图标。
更友好的时间处理
直观的时间格式配置,支持时区。
适用于脚本和库
轻松配置或禁用日志,避免污染依赖项目。
完全兼容标准 logging
模块
可与现有日志处理程序无缝集成。
通过环境变量自定义默认值
修改默认格式或颜色。
便捷的日志解析工具
支持正则提取和类型转换。
全面的通知集成
结合 apprise
库发送邮件、Discord 等通知。
10 倍于标准日志模块的速度
关键函数即将通过 C 实现进一步优化性能。
开箱即用
from loguru import logger
logger.debug("简洁、美观且易用的日志记录!")
默认预配置为输出到 stderr
,但可完全自定义。
通过 add()
函数配置日志输出目标(控制台、文件等):
logger.add(sys.stderr, format="{time} {level} {message}", filter="my_module", level="INFO")
移除处理器:使用 logger.remove()
。
覆盖默认配置:先调用 logger.remove()
再添加新处理器。
# 按时间自动生成日志文件
logger.add("file_{time}.log")
# 按大小轮转(500MB 轮转,保留旧文件)
logger.add("file_1.log", rotation="500 MB")
# 按时间轮转(每天中午或每周)
logger.add("file_2.log", rotation="12:00")
logger.add("file_3.log", rotation="1 week")
# 保留策略(10 天后清理)
logger.add("file_X.log", retention="10 days")
# 压缩日志(节省空间)
logger.add("file_Y.log", compression="zip")
logger.info("如果你在用 Python {},当然要选择 {feature}!", 3.6, feature="f-strings")
使用装饰器或上下文管理器自动记录异常:
@logger.catch
def risky_function():
return 1 / 0
logger.add(sys.stdout, colorize=True, format="{time} {message} ")
logger.add("somefile.log", enqueue=True) # 启用入队确保多进程安全
logger.add("out.log", backtrace=True, diagnose=True) # 生产环境慎用 diagnose=True
def func(a, b):
return a / b
def nested(c):
try:
func(5, c)
except ZeroDivisionError:
logger.exception("出错了!")
nested(0)
输出示例:
2024-01-31 14:34:56 | ERROR | __main__:nested:10 - 出错了!
Traceback (most recent call last):
File "test.py", line 12, in
nested(0)
File "test.py", line 8, in nested
func(5, c)
File "test.py", line 4, in func
return a / b
ZeroDivisionError: division by zero
# 序列化为 JSON
logger.add(custom_sink, serialize=True)
# 添加上下文信息
context_logger = logger.bind(ip="192.168.0.1", user="someone")
context_logger.info("轻松添加上下文")
# 临时上下文
with logger.contextualize(task=task_id):
logger.info("任务结束")
logger.opt(lazy=True).debug("生产环境不执行此计算: {x}", x=lambda: expensive(2**64))
new_level = logger.level("SNAKY", no=38, color="", icon="")
logger.log("SNAKY", "自定义级别日志")
logger.add("file.log", format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}")
# 脚本配置
config = {
"handlers": [
{"sink": sys.stdout, "format": "{time} - {message}"},
{"sink": "file.log", "serialize": True},
],
"extra": {"user": "someone"}
}
logger.configure(**config)
# 库中禁用日志
logger.disable("my_library")
# 使用标准 Handler
handler = logging.handlers.SysLogHandler(address=('localhost', 514))
logger.add(handler)
# 将 Loguru 日志传递到标准 logging
class PropagateHandler(logging.Handler):
def emit(self, record):
logging.getLogger(record.name).handle(record)
logger.add(PropagateHandler(), format="{message}")
# 拦截标准 logging 消息到 Loguru
class InterceptHandler(logging.Handler):
def emit(self, record):
level = logger.level(record.levelname).name
logger.opt(depth=6, exception=record.exc_info).log(level, record.getMessage())
logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
bash
# Linux/OSX
export LOGURU_FORMAT="{time} | {message} "
# Windows
setx LOGURU_DEBUG_COLOR ""
pattern = r"(?P
import apprise
notifier = apprise.Apprise()
notifier.add(f"discord://WEBHOOK_ID/WEBHOOK_TOKEN")
logger.add(notifier.notify, level="ERROR", filter={"apprise": False})
Loguru 的关键函数设计高效,未来将通过 C 实现进一步提速,使其在密集日志场景下表现卓越。
Loguru 以极简的 API 和强大的功能,重新定义了 Python 日志记录的体验。无论是小型脚本还是大型应用,它都能让日志记录变得直观、高效且愉悦。完整使用说明可访问 Loguru GitHub 主页。