Loguru库

日志级别

Loguru 默认有 8 个标准日志级别:

级别名称 数值 颜色 用途
TRACE 5 蓝色 最详细的追踪信息
DEBUG 10 蓝色 调试信息
INFO 20 白色 一般信息
SUCCESS 25 绿色 成功操作(Loguru特有)
WARNING 30 黄色 警告信息
ERROR 40 红色 错误信息
CRITICAL 50 红色加粗 严重错误

除此之外也可以自定义级别,实践如下:

1
2
logger.level("CUSTOM", no=38, color="<yellow>", icon="🔧")
logger.log("CUSTOM", "this is a custom level message")

异常追踪

自定义日志格式和输出

1
2
3
4
5
6
logger.remove()  # 移除默认处理器
logger.add(
sys.stderr,
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>",
level="INFO"
)

写入消息

1
2
3
logger.add("app.log", rotation="500 MB", encoding="utf-8")
# 文件名,文件大小,编码格式
logger.info(custom_message)

你只需要对同一个 logger 对象调用多次 add()方法,它就会自动把日志分发到所有配置好的目标(比如同时发给控制台和文件)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import sys
from loguru import logger

def main():
# 1. (可选) 清除默认的处理器,这样我们可以完全自定义
logger.remove()

# 2. 添加控制台输出 (Sink 1)
logger.add(
sys.stderr,
level="INFO",
format="<green>{time}</green> <level>{message}</level>"
)

# 3. 添加文件输出 (Sink 2)
logger.add(
"app.log",
rotation="500 MB",
encoding="utf-8",
level="DEBUG", # 文件可以记录更详细的日志
format="{time} - {level} - {message}"
)

# 4. 记录日志
# 这条日志会自动分发给上面配置的所有 Sink
logger.info("这条消息会同时出现在控制台和文件中")

# 如果文件级别是 DEBUG,控制台是 INFO
logger.debug("这条消息只会出现在文件中,不会出现在控制台")

if __name__ == "__main__":
main()

为什么不需要两个对象?

  1. 单例模式:from loguru import logger 导入的是一个单例对象。你不能像标准库那样实例化 new Logger()

  2. 统一管理:使用一个 logger 可以保证日志的时间戳、上下文(Context)在所有输出中是完全一致的。

如果你非要“两个看起来不一样的 Logger”

如果你是想实现:console_logger 只打控制台,file_logger 只打文件,Loguru 的做法是使用 bind + filter,而不是创建新对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import sys
from loguru import logger

# 定义过滤器
def filter_console(record):
return record["extra"].get("channel") == "console"

def filter_file(record):
return record["extra"].get("channel") == "file"

# 配置 Sink
logger.remove()
logger.add(sys.stderr, filter=filter_console)
logger.add("app.log", filter=filter_file)

# 创建两个“分身”
console_logger = logger.bind(channel="console")
file_logger = logger.bind(channel="file")

# 使用
console_logger.info("只在控制台")
file_logger.info("只在文件")