Loguru: 简单高效的Python日志记录方案

Loguru

在Python中,我们可以很容易使用logging模块来完成日志的记录,但是如果需要成系统地进行日志的记录和管理,还需要进行相关Formatter,Handler等配置,详情可以参考Python日志模块-logging - EverNorif。而Loguru是一个Python的第三方package,它提供简化的使用方式,使得我们无需进行复杂的配置就能够得到很好的日志管理效果。

loguru的项目地址为:Delgan/loguru: Python logging made (stupidly) simple。在使用之前,需要使用pip进行该package的安装。

1
pip install loguru

在标准的logging模块中,默认的日志功能输出的信息较为有限(当然可以通过Formatter进行配置)。而loguru提供了开箱即用的格式信息,默认输出已经非常丰富:

1
2
3
4
5
6
7
8
from loguru import logger

if __name__ == '__main__':
logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")

默认日志输出如下:

1
2
3
4
2023-10-28 12:54:55.799 | DEBUG    | __main__:<module>:4 - debug message
2023-10-28 12:54:55.799 | INFO | __main__:<module>:5 - info message
2023-10-28 12:54:55.799 | WARNING | __main__:<module>:6 - warning message
2023-10-28 12:54:55.799 | ERROR | __main__:<module>:7 - error message

在loguru中,不区分Handler、Formatter、Filter等概念,而是统一使用一个add方法来进行管理,包括增加新的handler、设置日志格式、过滤信息、设置日志等级等。

add方法可以理解为增加了一种日志处理的逻辑。loguru提供了默认的处理逻辑(输出到stderr,日志格式如上默认,日志等级为DEBUG),我们可以在此基础上新增加任何其他的处理逻辑,这些处理逻辑都是会同时生效的。

add方法返回一个logger的标识id,通过logger.remove(handler_id)方法可以禁用对应的日志处理逻辑。如果直接调用logger.remove()而不传入任何参数,则表示禁用默认的处理逻辑。

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

logger.remove() # 禁用默认处理逻辑

logger1 = logger.add(
sys.stdout, level='INFO',
format="[logger1]{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}"
)
logger.remove(logger1) # 禁用logger1对应的处理逻辑

logger2 = logger.add(
sys.stdout, level='WARNING',
format="[logger2]{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}"
)
# 最终只有logger2的处理逻辑生效

if __name__ == '__main__':
logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")

输出如下:

1
2
[logger2]2023-10-28 13:09:36 | WARNING | loguru-test:<module>:20 - warning message
[logger2]2023-10-28 13:09:36 | ERROR | loguru-test:<module>:21 - error message

注意上面我们使用f-string的方式来完成格式信息的配置,相比于logging的配置方式更加方便。

如果我们想要修改默认的logger的模式,那么就需要先调用logger.remove(),然后再使用add方法新增logger日志处理逻辑,即logger.add(sys.stdout, level='INFO')

当然这实际上是移除了默认的logger日志处理逻辑(stdout, level='DEBUG'),然后新增了想要的逻辑。

同样,我们可以在处理逻辑中配置将日志记录到文件中(可以看到其中可以配置对应时间作为日志文件名称):

1
2
3
logger.add(
'./my_log_{time:YYYY-MM-DD HH:mm:ss}.log'
)

在将日志记录到文件的时候,还可能会进行其他的配置,例如rotation、retention、compression等,这些操作都可以通过非常简单的配置项来指定。详细使用可以参考The file sinks - loguru.logger — loguru documentation

  • rotation:日志轮换,可以设置定时输出新的日志文件,也可以设置根据指定文件大小来决定是否输出新的日志文件
  • retention:设置日志的最长保存时间(近xx天等)
  • compression:日志压缩

记录日志的一大非常重要的作用就是让我们能够跟踪程序的异常情况,loguru提供如下的操作方式:

1
2
3
4
5
6
7
8
9
10
11
from loguru import logger


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


if __name__ == '__main__':
my_function(0, 1, -1)

此时loguru会输出如下的日志,可以看到在其中还记录了各个变量的值,方便我们进行异常分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2023-10-28 13:26:15.703 | ERROR    | __main__:<module>:10 - An error has been caught in function '<module>', process 'MainProcess' (8467), thread 'MainThread' (8014304000):
Traceback (most recent call last):

> File "/Users/evernorif/Project/Python/PlayGround/python/loguru-test.py", line 10, in <module>
my_function(0, 1, -1)
└ <function my_function at 0x103de6040>

File "/Users/evernorif/Project/Python/PlayGround/python/loguru-test.py", line 6, in my_function
return 1 / (x + y + z)
│ │ └ -1
│ └ 1
0

ZeroDivisionError: division by zero

以上介绍了loguru的一些基本使用。作为一个专注在日志记录的package,loguru还提供了一些其他使用的feature,例如:

  • 日志结构化
  • 自定义日志级别
  • 与其他通知模块(eg,liiight/notifiers,...)集成
  • ...

详细使用可以参考官方文档

参考文章

  1. 为什么不推荐使用Python原生日志库?
  2. Python 中更优雅的日志记录方案 loguru | 静觅

Loguru: 简单高效的Python日志记录方案
http://example.com/2023/10/28/Loguru-简单高效的Python日志记录方案/
作者
EverNorif
发布于
2023年10月28日
许可协议