
loguru 的 logger 是全局单例,多次 `add()` 会向同一 logger 添加多个处理器(sinks),所有满足级别阈值的日志都会广播到所有匹配的 sink——因此 error 日志同时写入 info 和 error 文件。解决方法是使用 `filter` 参数精确控制每条日志的路由。
在 Loguru 中,logger 对象本质上是全局的(from loguru import logger 导入的是同一个实例),因此 loggerEven = logger 和 loggerUneven = logger 并未创建独立 logger,只是两个指向同一对象的引用。调用 logger.add(..., level="INFO") 和 logger.add(..., level="ERROR") 实际上是为同一个 logger添加了两个文件 sink。Loguru 的日志分发机制是:每条日志消息会依次经过所有已注册 sink,只要该 sink 的 level 阈值 ≤ 当前日志级别,就会被写入。
因此,当执行 logger.error("Uneven") 时:
- "UnEven.txt" sink 的 level="ERROR" ✅ 匹配 → 写入;
- "Even.txt" sink 的 level="INFO"(INFO
⚠️ 关键误区:level 控制的是“最低可接收级别”,而非“专属级别”。它不能实现“仅 ERROR 写入 error 文件、仅 INFO 写入 info 文件”的排他路由。
✅ 正确解法:使用 filter 参数(支持函数或字符串)对每个 sink 做精细化过滤。推荐使用函数形式,返回 True 表示允许该日志进入此 sink:
from loguru import logger
import random
# 清空默认 handler(可选,避免控制台重复输出)
logger.remove()
# 只接收 INFO 级别且 message 不含 "ERROR" 的日志(示例逻辑)
logger.add("Even.txt", mode='w', level="INFO",
filter=lambda record: record["level"].no == 20) # INFO 的数值为 20
# 只接收 ERROR 级别日志
logger.add("UnEven.txt", mode='w', level="ERROR",
filter=lambda record: record["level"].no == 40) # ERROR 的数值为 40
x = random.randint(0, 11)
print(x)
if x % 2 == 1:
logger.error("Uneven")
else:
logger.info("Even")更灵活的方式是基于日志内容、模块名或自定义字段过滤:
# 按日志消息关键字过滤(不推荐用于生产,仅作演示)
logger.add("errors_only.log", level="ERROR",
filter=lambda r: "critical" in r["message"].lower() or r["level"].name == "ERROR")
# 或使用字典式 filter(推荐用于多条件)
def error_only_filter(record):
return record["level"].name in ["ERROR", "CRITICAL"]
logger.add("app_errors.log", level="ERROR", filter=error_only_filter)? 注意事项:
- filter 函数接收 record 字典(含 level, message, module, function, time 等键),务必确保逻辑无副作用且返回布尔值;
- 若需完全隔离日志流(如不同模块/组件使用独立日志器),应使用 logger.bind() + filter 组合,或按官方 Recipe 创建命名子 logger(通过 logger.opt() 或封装类);
- 避免在 filter 中执行耗时操作(如 I/O、网络请求),否则会阻塞日志主线程;
- 调试时可用 logger.debug("Record: {}", record)(需先启用 DEBUG 级别)查看实际 record 结构。
总结:Loguru 的核心设计是“一个 logger,多个 sink,广播式分发”,level 仅做最小门槛控制;真正实现精准路由必须依赖 filter。合理组合 level(粗筛)与 filter(精筛),即可优雅达成“ERROR 只进 error 文件、INFO 只进 info 文件”的目标。










