大家好,我是jobleap.cn的小九。
Loguru 是 Python 中一款简洁、强大且易用的日志库,核心优势是零配置启动、API 直观、功能全面(支持日志轮转、过滤、格式化、异常捕获等),无需像标准库 logging 那样繁琐配置。本文将从基础到进阶,串联所有常用 API,结合实战示例帮你彻底掌握 Loguru 的用法。
一、准备工作:安装 Loguru
首先通过 pip 安装(支持 Python 3.5+):
pip install loguru
核心特性:
- 无需手动创建
logger实例,直接导入即用 - 默认输出彩色日志到控制台,格式清晰
- 一行代码实现文件日志、轮转、压缩等高级功能
- 内置异常捕获与堆栈追踪功能
二、基础用法:快速上手
Loguru 的核心是 logger 对象,直接导入即可使用,无需额外配置。
2.1 基本日志输出(默认控制台)
Loguru 定义了 7 个日志级别(从低到高):TRACE < DEBUG < INFO < SUCCESS < WARNING < ERROR < CRITICAL,对应 7 个常用方法:
from loguru import logger
# 不同级别日志输出
logger.trace("最详细的调试信息(默认不显示)")
logger.debug("调试信息")
logger.info("普通业务信息")
logger.success("操作成功") # Loguru 独有的 SUCCESS 级别
logger.warning("警告信息")
logger.error("错误信息")
logger.critical("严重错误(如程序崩溃)")
运行结果(控制台彩色输出):
2025-11-26 10:00:00.123 | DEBUG | __main__:<module>:4 - 调试信息
2025-11-26 10:00:00.124 | INFO | __main__:<module>:5 - 普通业务信息
2025-11-26 10:00:00.124 | SUCCESS | __main__:<module>:6 - 操作成功
2025-11-26 10:00:00.124 | WARNING | __main__:<module>:7 - 警告信息
2025-11-26 10:00:00.124 | ERROR | __main__:<module>:8 - 错误信息
2025-11-26 10:00:00.125 | CRITICAL | __main__:<module>:9 - 严重错误(如程序崩溃)
- 默认不显示
TRACE级别(需手动开启) - 日志格式默认包含:时间、级别、模块名、函数名、行号、日志信息
2.2 核心 API:logger.add() 详解(日志写入文件)
add() 是 Loguru 最核心的 API,用于添加日志输出目标(文件、网络、自定义 sink 等),支持所有高级功能。其常用参数如下:
| 参数 | 作用 |
|---|---|
sink | 输出目标(文件路径字符串、文件对象、自定义函数/类) |
level | 日志级别阈值(低于该级别的日志不输出) |
format | 自定义日志格式 |
rotation | 日志轮转规则(按大小、时间、文件数) |
retention | 日志保留策略(保留天数、文件数) |
compression | 日志压缩格式(zip/gz/bz2/xz) |
filter | 日志过滤规则(函数/字典) |
encoding | 文件编码(如 "utf-8") |
示例 1:基本文件日志(无轮转)
from loguru import logger
# 添加文件输出(所有级别≥DEBUG的日志写入文件)
logger.add(
sink="app.log", # 日志文件路径
level="DEBUG", # 日志级别阈值
format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}", # 自定义格式
encoding="utf-8" # 避免中文乱码
)
# 测试日志
logger.debug("写入文件的调试信息")
logger.error("写入文件的错误信息")
示例 2:日志轮转(生产环境必备)
解决单文件过大问题,支持 3 种轮转方式:
from loguru import logger
# 方式 1:按文件大小轮转(每个文件最大 500MB,自动创建新文件)
logger.add("app_size.log", rotation="500 MB")
# 方式 2:按时间轮转(每天凌晨 00:00 新建文件)
logger.add("app_daily.log", rotation="00:00")
# 方式 3:按时间间隔轮转(每 1 周新建文件)
logger.add("app_weekly.log", rotation="1 week")
# 方式 4:限制文件数量(最多保留 10 个文件,超量自动删除最旧的)
logger.add("app_limit.log", rotation="500 MB", retention=10)
# 方式 5:保留指定天数(最多保留 7 天的日志)
logger.add("app_retention.log", rotation="00:00", retention="7 days")
# 方式 6:轮转后自动压缩(节省磁盘空间)
logger.add("app_compress.log", rotation="500 MB", compression="zip")
三、进阶用法:串联核心 API
3.1 自定义日志格式
通过 format 参数自定义日志字段,支持 Loguru 内置变量(完整变量列表见官方文档),常用变量:
{time}:日志时间(可指定格式,如{time:YYYY-MM-DD HH:mm:ss.SSS}){level}:日志级别(可显示颜色{level: <8}左对齐){message}:日志内容{name}:模块名{function}:函数名{line}:代码行号{extra}:通过bind()绑定的额外上下文信息
from loguru import logger
# 自定义格式(包含模块、函数、行号和上下文信息)
logger.add(
"custom_format.log",
format="""{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} |
模块:{name} | 函数:{function} | 行号:{line} |
信息:{message} | 上下文:{extra[user_id]}""",
level="INFO"
)
# 绑定上下文信息(通过 bind() 添加 extra 字段)
logger.bind(user_id=1001).info("用户登录成功")
logger.bind(user_id=1002).error("用户支付失败")
输出效果:
2025-11-26 10:30:00.123 | INFO | 模块:__main__ | 函数:<module> | 行号:12 | 信息:用户登录成功 | 上下文:1001
2025-11-26 10:30:00.124 | ERROR | 模块:__main__ | 函数:<module> | 行号:13 | 信息:用户支付失败 | 上下文:1002
3.2 日志过滤:filter 参数
通过 filter 筛选需要输出的日志,支持 2 种用法:
用法 1:按级别/模块过滤(字典格式)
from loguru import logger
# 只输出 ERROR 级别且模块名为 "payment" 的日志
logger.add(
"filtered.log",
filter={"level": "ERROR", "name": "payment"}
)
用法 2:自定义过滤函数(灵活控制)
from loguru import logger
# 过滤规则:只保留 user_id=1001 或级别≥ERROR 的日志
def filter_log(record):
user_id = record["extra"].get("user_id")
return user_id == 1001 or record["level"].no >= logger.level("ERROR").no
# 添加带过滤的文件输出
logger.add("custom_filter.log", filter=filter_log)
# 测试:只有 user_id=1001 和 ERROR 日志会被写入
logger.bind(user_id=1001).info("用户1001的信息")
logger.bind(user_id=1002).info("用户1002的信息(被过滤)")
logger.error("错误日志(不被过滤)")
3.3 异常捕获:logger.exception() 与 @logger.catch
Loguru 简化了异常日志记录,无需手动拼接堆栈信息。
用法 1:logger.exception()(捕获显式异常)
在 try-except 中使用,自动记录完整堆栈:
from loguru import logger
logger.add("exception.log", level="DEBUG")
try:
1 / 0 # 触发除零错误
except Exception as e:
# 自动记录异常类型、消息和完整堆栈
logger.exception("除零错误发生:{}", e)
用法 2:@logger.catch(捕获函数内所有异常)
装饰器形式,自动捕获函数执行过程中的所有未处理异常:
from loguru import logger
logger.add("catch_exception.log", level="DEBUG")
# 装饰器:自动捕获函数内的异常并记录
@logger.catch
def calculate(a, b):
return a / b
# 调用函数(触发异常,自动记录)
calculate(1, 0)
日志输出(包含完整堆栈追踪):
2025-11-26 11:00:00.123 | ERROR | __main__:calculate:8 - An error has been caught in function 'calculate', process 'MainProcess' (1234), thread 'MainThread' (5678)
Traceback (most recent call last):
File "test.py", line 11, in <module>
calculate(1, 0)
File "test.py", line 8, in calculate
return a / b
ZeroDivisionError: division by zero
3.4 上下文绑定:logger.bind() 与 logger.patch()
用于添加固定上下文信息(如用户 ID、请求 ID、服务器 IP 等),避免重复写入。
用法 1:logger.bind()(静态绑定)
绑定后返回新的 logger 实例,后续调用该实例会携带上下文:
from loguru import logger
logger.add("context.log", format="{time} | {level} | user_id:{extra[user_id]} | {message}")
# 绑定 user_id=1001,返回新 logger
user_logger = logger.bind(user_id=1001)
user_logger.info("登录系统")
user_logger.warning("密码即将过期")
# 绑定新的上下文(不影响原实例)
admin_logger = logger.bind(user_id=9999, role="admin")
admin_logger.success("执行管理员操作")
用法 2:logger.patch()(动态绑定)
通过函数动态生成上下文信息(如请求 ID 每次不同):
from loguru import logger
import uuid
logger.add("dynamic_context.log", format="{time} | req_id:{extra[req_id]} | {message}")
# 动态生成请求 ID(每次调用日志方法时执行)
def generate_req_id(record):
record["extra"]["req_id"] = str(uuid.uuid4())[:8] # 生成 8 位随机 ID
# 绑定动态上下文
req_logger = logger.patch(generate_req_id)
# 每次调用都会生成新的 req_id
req_logger.info("处理用户请求")
req_logger.error("请求参数错误")
3.5 日志移除:logger.remove()
logger.add() 会返回一个唯一 ID,通过该 ID 可移除对应的输出目标(如关闭文件日志):
from loguru import logger
# 添加文件日志,获取 ID
file_log_id = logger.add("temp.log", level="INFO")
# 输出日志(会写入文件)
logger.info("测试移除前的日志")
# 移除文件日志(后续日志不再写入 temp.log)
logger.remove(file_log_id)
# 后续日志只输出到控制台
logger.info("测试移除后的日志")
# 移除所有输出目标(谨慎使用!后续无日志输出)
# logger.remove()
3.6 全局配置:logger.configure()
批量配置 logger 的输出目标、格式等,适合统一管理:
from loguru import logger
# 批量配置:同时输出到控制台和文件
logger.configure(
handlers=[
# 控制台输出(彩色、INFO级别以上)
{
"sink": sys.stderr,
"level": "INFO",
"format": "<green>{time}</green> | <level>{message}</level>"
},
# 文件输出(轮转、压缩、保留7天)
{
"sink": "app_config.log",
"level": "DEBUG",
"format": "{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
"rotation": "1 day",
"retention": "7 days",
"compression": "gz"
}
]
)
logger.debug("配置后的调试日志(仅文件输出)")
logger.info("配置后的信息日志(控制台+文件输出)")
3.7 自定义 Sink:扩展输出目标
sink 不仅支持文件路径,还可以是函数或类实例,实现日志转发到数据库、消息队列等自定义场景。
示例:自定义 Sink 函数(日志写入数据库)
from loguru import logger
import sqlite3
# 初始化数据库
conn = sqlite3.connect("log.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS logs (time TEXT, level TEXT, message TEXT)")
conn.commit()
# 自定义 sink 函数:将日志写入 SQLite
def db_sink(record):
time = record["time"].strftime("%Y-%m-%d %H:%M:%S")
level = record["level"].name
message = record["message"]
# 插入数据库
cursor.execute("INSERT INTO logs (time, level, message) VALUES (?, ?, ?)", (time, level, message))
conn.commit()
# 添加自定义 sink
logger.add(db_sink, level="INFO")
# 测试:日志会同时输出到控制台和数据库
logger.info("数据库日志测试")
logger.error("数据库错误日志")
四、综合实战:生产环境日志配置
下面整合所有常用 API,实现一个生产级别的日志配置:
from loguru import logger
import sys
# 移除默认控制台输出(可选,重新自定义)
logger.remove()
# 配置日志:控制台 + 文件轮转 + 过滤 + 格式化
def setup_logger():
# 1. 控制台输出(彩色、INFO级别以上)
logger.add(
sink=sys.stderr,
level="INFO",
format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
"<level>{level: <8}</level> | "
"<cyan>{name}</cyan>:<cyan>{line}</cyan> - "
"<level>{message}</level>",
colorize=True # 启用彩色输出
)
# 2. 文件输出(按大小轮转、压缩、保留15天、过滤ERROR以上日志)
logger.add(
sink="logs/app_{time:YYYY-MM-DD}.log", # 文件名包含日期
level="DEBUG",
format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level} | {name}:{function}:{line} | {extra[req_id]} | {message}",
rotation="100 MB", # 每100MB轮转
retention="15 days", # 保留15天
compression="gz", # 压缩为gz格式
encoding="utf-8",
filter=lambda record: record["level"].no >= logger.level("DEBUG").no # 只保留DEBUG以上
)
# 3. 错误日志单独文件(仅记录ERROR以上级别)
logger.add(
sink="logs/error_{time:YYYY-MM-DD}.log",
level="ERROR",
format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level} | {name}:{function}:{line} | {extra[req_id]} | {message}\n{exception}",
rotation="1 day",
retention="30 days",
compression="zip"
)
# 初始化日志配置
setup_logger()
# 模拟 Web 请求场景:绑定请求 ID
def handle_request(user_id, req_id):
# 绑定上下文(req_id 和 user_id)
req_logger = logger.bind(req_id=req_id, user_id=user_id)
req_logger.info("开始处理用户请求")
try:
# 模拟业务逻辑
if user_id == 0:
raise ValueError("用户ID不能为0")
req_logger.success("请求处理完成")
except Exception as e:
req_logger.exception("请求处理失败:{}", e)
# 测试
if __name__ == "__main__":
handle_request(user_id=1001, req_id="req-20251126-001")
handle_request(user_id=0, req_id="req-20251126-002") # 触发异常
五、关键 API 总结
| API | 用途 | 核心场景 |
|---|---|---|
logger.<level>() | 输出对应级别日志 | 日常日志记录 |
logger.add() | 添加日志输出目标(文件/自定义sink) | 文件日志、轮转、压缩 |
logger.remove() | 移除输出目标 | 关闭文件日志、动态调整 |
logger.bind() | 绑定上下文信息 | 携带用户ID、请求ID |
logger.patch() | 动态生成上下文信息 | 随机请求ID、动态环境变量 |
logger.exception() | 记录异常及堆栈 | 显式异常捕获 |
@logger.catch | 自动捕获函数异常 | 批量异常监控(如接口、任务) |
logger.configure() | 全局批量配置日志 | 统一管理输出目标和格式 |
六、常见问题
- 中文乱码:在
add()中指定encoding="utf-8"。 - 默认控制台不显示 TRACE 级别:添加
logger.add(sys.stderr, level="TRACE")手动开启。 - 日志轮转不生效:检查
rotation参数格式(如 "500 MB" 带空格,"00:00" 是字符串)。 - 异常日志没有堆栈:使用
logger.exception()而非logger.error()。
通过以上教程,你已经掌握了 Loguru 的所有常用 API 和实战场景。Loguru 的设计哲学是“简洁而不简单”,日常开发中可直接套用本文的生产级配置,无需额外复杂操作。更多高级功能可参考 Loguru 官方文档。