第三方 Python 库 Loguru 的基础使用

Python logging made (stupidly) simple —— 让日志记录简单到"愚蠢"。

本文是 Loguru 系列的第一篇,带你从零认识 Loguru,掌握日常开发中最常用的基础功能。读完这篇,你就能把 print() 扔掉,用上正经的日志了。


系列文章导航:

一、背景:为什么每个 Python 开发者都该重视日志?

做开发的朋友应该都有过这样的经历:程序跑着跑着出了问题,你一脸懵地盯着屏幕,心里想"到底是哪里炸了?"。这时候,如果你的代码里有完善的日志记录,翻一翻日志文件就能快速定位问题;如果没有……那就只能靠祈祷了。

日志就像是飞机的"黑匣子",它忠实地记录着程序运行过程中发生的一切。在正确的时间看到正确的日志,可能就是"5 分钟修好 bug"和"通宵排查到天亮"的区别。

但现实是,很多 Python 开发者(尤其是初学者)在调试时更习惯用 print()。不是不知道日志重要,而是标准库 logging 用起来太麻烦了。

来看一个最简单的例子,用标准 logging 输出一条日志:

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
logger.info("Hello, logging!")

看起来还行?但当你需要把日志同时输出到控制台和文件、按大小轮转、自动压缩、加点颜色……配置代码就会像滚雪球一样越写越多。很多团队甚至会专门封装一个 log_helper.py 来处理这些事情。

所以,有没有一种方案,能让我们开箱即用,一行代码搞定日志?

有的,它就是今天的主角——Loguru


二、Loguru 是什么?

Loguru 是一个第三方 Python 日志库,GitHub 上有超过 23k 的 Star,可以说是目前最流行的 Python 日志方案之一。

它的设计理念很简单:日志记录不应该是一件痛苦的事。 你不需要配置 Handler、Formatter、Filter 这些东西,一行 from loguru import logger 就能开始干活。

官方的原话是这么说的:

Did you ever feel lazy about configuring a logger and used print() instead? I did, yet logging is fundamental to every application. Using Loguru you have no excuse not to use logging from the start.

翻译过来就是:你有没有因为懒得配置 logger 而直接用 print()?凶手就是我。但有了 Loguru,你再也没有借口不写日志了。

Loguru 的核心特性

  • 开箱即用:不需要任何配置,导入就能用
  • 一个函数搞定一切add() 代替了 Handler、Formatter、Filter 三件套
  • 内置日志管理:轮转、保留、压缩,一个参数搞定
  • 彩色输出:终端自动带颜色,不同级别一目了然
  • 增强的异常追踪:比标准 logging 多显示变量值,堪比调试器
  • 线程安全、多进程安全:不用担心并发问题
  • 兼容标准 logging:可以和已有的 logging 配置共存

三、Loguru vs 标准 logging:一张表看懂差异

在深入用法之前,我们先来对比一下两者的核心差异:

特性 标准 logging Loguru
上手难度 需要配置 Handler/Formatter/Filter 一行导入,开箱即用
输出到文件 需要手动添加 FileHandler 直接传文件路径字符串
日志轮转 需要 RotatingFileHandler rotation="500 MB" 一个参数
日志保留 需要自己写清理逻辑 retention="10 days" 自动清理
日志压缩 不支持,需要额外处理 compression="zip" 自动压缩
彩色输出 不支持 终端自动彩色
异常追踪 默认信息较少 显示完整变量值
字符串格式化 %s%d {} 花括号风格,更现代
日志级别 5 个 7 个(多了 TRACE 和 SUCCESS)

简单来说,Loguru 把你在标准 logging 里需要写几十行才能搞定的事情,压缩到了一两行。这不是魔法,这是好的 API 设计。


四、安装

pip install loguru

就这一行,没有额外依赖。支持 Python 3.5 及以上版本。

安装完可以验证一下:

from loguru import logger
print(logger)
# <loguru.logger handlers=[(id=0, level=10, sink=<stderr>)]>

看到类似输出,说明安装成功了。注意这里有一个默认的 handler,它会把日志输出到 stderr(标准错误流),这就是为什么你什么都不配置也能看到日志。


五、快速上手:第一个 Loguru 程序

5.1 基本日志输出

from loguru import logger

logger.debug("这是一条调试日志")
logger.info("这是一条信息日志")
logger.success("这是一条成功日志")
logger.warning("这是一条警告日志")
logger.error("这是一条错误日志")
logger.critical("这是一条严重错误日志")

运行后你会看到类似这样的输出(带颜色的):

2026-06-08 10:30:15.123 | DEBUG    | __main__:<module>:3 - 这是一条调试日志
2026-06-08 10:30:15.123 | INFO     | __main__:<module>:4 - 这是一条信息日志
2026-06-08 10:30:15.123 | SUCCESS  | __main__:<module>:5 - 这是一条成功日志
2026-06-08 10:30:15.123 | WARNING  | __main__:<module>:6 - 这是一条警告日志
2026-06-08 10:30:15.123 | ERROR    | __main__:<module>:7 - 这是一条错误日志
2026-06-08 10:30:15.123 | CRITICAL | __main__:<module>:8 - 这是一条严重错误日志

注意看,每条日志自动包含了时间戳、日志级别、文件名、函数名、行号,这些信息在排查问题时非常有用。而且 SUCCESS 这个级别是 Loguru 独有的,标准 logging 里没有。

5.2 日志级别一览

Loguru 提供了 7 个内置日志级别,从低到高排列:

级别 数值 用途 颜色
TRACE 5 比 DEBUG 更细粒度的追踪
DEBUG 10 调试信息,开发时用
INFO 20 常规运行信息
SUCCESS 25 操作成功(Loguru 独有) 绿色
WARNING 30 警告,可能有问题 黄色
ERROR 40 错误,部分功能失败 红色
CRITICAL 50 严重错误,程序可能无法继续 红色

默认情况下,TRACE 级别的日志不会显示。如果需要开启,可以手动设置:

logger.add(sys.stderr, level="TRACE")

5.3 字符串格式化

标准 logging%s%d 来格式化,Loguru 用更现代的花括号风格,和 Python 的 f-string 一样自然:

from loguru import logger

name = "张三"
age = 25

# 花括号风格
logger.info("用户 {} 今年 {} 岁", name, age)

# 关键字参数
logger.info("用户 {name} 今年 {age} 岁", name=name, age=age)

# 混合使用
logger.info("Python {},当然要用 {feature}!", 3.12, feature="f-strings")

这种方式比 %s 直观多了,而且不会出现 %s%d 搞混的问题。


六、日志输出到文件

用标准 logging 输出到文件,你需要创建 FileHandler、设置 Formatter、添加到 Logger……用 Loguru 的话:

from loguru import logger

logger.add("app.log")
logger.info("这条日志会同时输出到控制台和 app.log 文件")

对,就这么简单。传一个文件路径字符串就行。而且注意,控制台的输出还在,add() 是"添加"一个新的输出目标,不是"替换"。


七、日志轮转、保留与压缩

这是 Loguru 最实用的功能之一,也是很多人从标准 logging 转过来的主要原因。

7.1 日志轮转(Rotation)

想象一下,你的服务跑了三个月,日志文件涨到了 50G,磁盘直接爆了。有了轮转机制,日志文件到了指定大小或时间就会自动"翻篇"。

from loguru import logger

# 按大小轮转:文件超过 500MB 就创建新文件
logger.add("app.log", rotation="500 MB")

# 按时间轮转:每天中午 12 点创建新文件
logger.add("app.log", rotation="12:00")

# 按时间间隔轮转:每周轮转一次
logger.add("app.log", rotation="1 week")

你也可以自定义轮转函数:

def should_rotate(message, file):
    """文件超过 10MB 就轮转"""
    file.seek(0, 2)  # 移到文件末尾
    return file.tell() + len(message) > 10 * 1024 * 1024

logger.add("app.log", rotation=should_rotate)

7.2 日志保留(Retention)

磁盘空间是有限的,老的日志终究要清理。retention 参数帮你自动做这件事:

from loguru import logger

# 只保留最近 10 天的日志,超过的自动删除
logger.add("app.log", retention="10 days")

# 只保留最近 10 个日志文件
logger.add("app.log", retention=10)

再也不用写 cron 脚本去定时清理日志了,Loguru 帮你搞定。

7.3 日志压缩(Compression)

旧日志删掉可惜,留着又占空间?压缩一下:

from loguru import logger

# 轮转后的日志自动压缩为 zip 格式
logger.add("app.log", compression="zip")

# 也支持 gzip
logger.add("app.log", compression="gz")

7.4 三件套组合

rotation + retention + compression 组合起来,就是一个完整的日志生命周期管理方案:

logger.add(
    "logs/app_{time:YYYY-MM-DD}.log",
    rotation="00:00",       # 每天零点轮转
    retention="30 days",    # 保留 30 天
    compression="zip",      # 旧日志压缩
    encoding="utf-8",       # 编码格式
)

这一行代码就实现了:每天自动创建新日志文件、自动清理 30 天前的旧文件、旧文件自动压缩。用标准 logging 实现同样的功能,至少得写几十行。


八、自定义日志格式

Loguru 默认的格式已经很好了,但你当然可以自定义:

from loguru import logger
import sys

# 先移除默认的控制台输出
logger.remove()

# 添加自定义格式的输出
logger.add(
    sys.stdout,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
           "<level>{level: <8}</level> | "
           "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | "
           "<level>{message}</level>",
    colorize=True
)

logger.info("自定义格式的日志")

格式里常用的占位符:

占位符 含义
{time} 时间戳,可指定格式如 {time:YYYY-MM-DD HH:mm:ss}
{level} 日志级别
{message} 日志内容
{name} 模块名
{function} 函数名
{line} 行号
{extra} 通过 bind() 绑定的额外信息

颜色标签用 <green><red><cyan> 等,<level> 会根据日志级别自动变色。

注意: 如果 format 里没有颜色标签,就算设置 colorize=True 也没效果。另外,如果你不先 logger.remove(),控制台会出现两条重复的日志(默认的一条 + 你新加的一条)。


九、日志过滤

有时候你不想看到所有模块的日志,只想看某个模块的,或者只看某个级别以上的:

from loguru import logger

# 只记录 my_module 模块的日志
logger.add("app.log", filter="my_module", level="INFO")

# 用字典过滤:指定模块的日志级别
logger.add("app.log", filter={"my_module": "INFO", "other_module": "WARNING"})

# 用函数做更灵活的过滤
logger.add("special.log", filter=lambda record: "special" in record["extra"])
logger.bind(special=True).info("这条会写入 special.log")
logger.debug("这条不会")

十、异常捕获

10.1 基本用法:logger.exception()

try-except 中使用,自动记录完整堆栈:

from loguru import logger

try:
    result = 1 / 0
except ZeroDivisionError:
    logger.exception("除零错误")

10.2 增强的异常追踪

这是 Loguru 的"杀手级"功能。标准 logging 的异常追踪信息很简陋,Loguru 则会把变量的值都打出来,堪比调试器:

from loguru import logger

logger.add("error.log", backtrace=True, diagnose=True)

def func(a, b):
    return a / b

def nested(c):
    try:
        func(5, c)
    except ZeroDivisionError:
        logger.exception("What?!")

nested(0)

输出的异常追踪信息长这样:

2026-06-08 10:30:15.123 | ERROR | __main__:nested:10 - What?!
Traceback (most recent call last):

  File "test.py", line 12, in <module>
    nested(0)
    └ <function nested at 0x7f5c755322f0>

> File "test.py", line 8, in nested
    func(5, c)
    │       └ 0
    └ <function func at 0x7f5c79fc2e18>

  File "test.py", line 4, in func
    return a / b
           │   └ 0
           └ 5

ZeroDivisionError: division by zero

看到了吗?变量 c 的值是 0a 的值是 5,一目了然。这在排查复杂调用链的问题时简直是神器。

注意: diagnose=True 会把变量值打到日志里,生产环境要注意敏感数据泄露的风险。建议开发环境开启,生产环境关闭。

10.3 @logger.catch 装饰器

对于异常捕获,Loguru 还提供了一个更优雅的方式——用装饰器:

from loguru import logger

@logger.catch
def my_function(x, y, z):
    return 1 / (x + y + z)

# 即使这里抛出 ZeroDivisionError,也会被 Loguru 捕获并记录
my_function(0, 0, 0)

@logger.catch 包一下,函数里的任何异常都会被自动捕获并输出详细的追踪信息。你再也不用到处写 try...except 了。

它也可以当上下文管理器用:

with logger.catch():
    # 这段代码里的任何异常都会被捕获
    do_something()
    do_something_else()

十一、移除日志处理器

logger.add() 会返回一个 ID,你可以用这个 ID 来移除对应的处理器:

from loguru import logger

# 添加一个文件日志,获取 ID
file_id = logger.add("temp.log", level="INFO")
logger.info("这条会写入 temp.log")

# 移除这个文件日志
logger.remove(file_id)
logger.info("这条不会写入 temp.log 了")

# 不带参数的 remove() 会移除所有处理器(包括默认的 stderr)
# logger.remove()  # 谨慎使用!移除后就没有日志输出了

这个功能在需要动态调整日志配置时很有用。比如在测试环境中,你可能想移除默认的控制台输出,换成自己的格式。


十二、自定义日志级别

Loguru 的 7 个内置级别通常够用了,但如果你有特殊需求,也可以自定义:

from loguru import logger

# 自定义一个 SNAKY 级别(数值 38,介于 WARNING 和 ERROR 之间)
logger.level("SNAKY", no=38, color="<yellow>", icon="🐍")
logger.log("SNAKY", "Here we go!")

自定义级别需要指定:

  • no:级别数值,决定了它在日志体系中的位置
  • color:在终端中显示的颜色
  • icon:在日志中显示的图标

十三、通过环境变量配置

不想改代码?Loguru 支持通过环境变量来调整默认行为:

# Linux / macOS
export LOGURU_LEVEL="DEBUG"
export LOGURU_FORMAT="{time} | <lvl>{message}</lvl>"

# Windows
set LOGURU_LEVEL=DEBUG
set LOGURU_FORMAT={time} | <lvl>{message}</lvl>

环境变量的名字和 logger.add() 的参数一一对应,非常直观。常用的环境变量:

  • LOGURU_LEVEL:默认日志级别
  • LOGURU_FORMAT:默认日志格式
  • LOGURU_DEBUG_COLOR:DEBUG 级别的颜色
  • NO_COLOR:禁用颜色输出
  • FORCE_COLOR:强制启用颜色输出

十四、小结

到这里,你已经掌握了 Loguru 最常用的基础功能:

  1. 一行导入from loguru import logger
  2. 7 个日志级别tracedebuginfosuccesswarningerrorcritical
  3. 输出到文件logger.add("file.log")
  4. 日志轮转rotation="500 MB"rotation="00:00"
  5. 日志保留retention="10 days"
  6. 日志压缩compression="zip"
  7. 自定义格式format=...,支持颜色标签
  8. 异常捕获logger.exception()@logger.catch
  9. 环境变量配置LOGURU_LEVELLOGURU_FORMAT

这些功能已经能覆盖日常开发 80% 的需求了。如果你还想了解更多高级用法——比如结构化日志、上下文绑定、懒求值、与标准 logging 互操作、多进程安全等——请继续阅读本系列的第二篇:《第三方 Python 库 Loguru 的进阶实战》。


延伸阅读

更多推荐