徐高翔的个人网站

Python实用模块推荐(十三)logging

2019-08-26

软硬件环境

  • ubuntu 19.04 64bit
  • anaconda3 with python 3.7.3
  • logging 0.5.1.2

简介

软件运行时难免出现问题,日志是追踪问题的一种方式。不管是在软件的开发阶段、调试阶段或者上线后,日志都非常重要。当程序crash掉而你没有保存日志,那将是灾难性的,损失将非常巨大,而且几乎没有可能找到问题的所在。

print语句可以用来输出调试信息,但是它不是一个好的选择。在简单的脚本中它可能管用,但是随着项目的变大、变复杂,print不会被采用。

python中有一个内置模块logging,它可以将程序运行的信息写入到文件或者其它输出流(如标准输出stdout)当中。

logging消息的级别

按照消息的严重程度,可分为

  • Debug : 详细的信息,调试阶段常用
  • Info : 程序正常运行的一些信息
  • Warning : 警告信息,代码可以继续运行,但是结果可能不是你想要的
  • Error : 程序已经出现错误
  • Critical : 非常严重的错误,程序可能无法继续运行

logging中,各级别又对应了一个整数,如下表

级别 整数
NOSET 0
DEBUG 10
INFO 20
WARNING 30
ERROR 40
CRITICAL 50

代码实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 导入模块
import logging

# 创建并配置logger,保存到文件
logging.basicConfig(filename="log.txt",
format='%(asctime)s %(message)s',
filemode='w')

# 创建一个对象,参数传入__name__,在模块中就是模块的名称
logger=logging.getLogger(__name__)

# 设置消息的日志层级,在这里,所以高于DEBUG层级的消息都会被写入文件
logger.setLevel(logging.DEBUG)

# 测试
logger.debug("This is debug message.")
logger.info("This is info message.")
logger.warning("This is warning message.")
logger.error("This is error message.")
logger.critical("This is critical message.")

程序执行后,log.txt文件内容为

script
1
2
3
4
5
2019-08-20 17:34:54,362 This is debug message.
2019-08-20 17:34:54,362 This is info message.
2019-08-20 17:34:54,362 This is warning message.
2019-08-20 17:34:54,362 This is error message.
2019-08-20 17:34:54,362 This is critical message.

Logger对象和Handler对象都可以设置级别,而默认Logger对象级别为30 ,也即WARNING,默认Handler对象级别为0,也即NOTSETlogging模块这样设计是为了更好的灵活性,比如有时候我们既想在控制台中输出DEBUG级别的日志,又想在文件中输出WARNING级别的日志。可以只设置一个最低级别的Logger对象,两个不同级别的Handler对象,示例代码如下

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
import logging
import logging.handlers

logger = logging.getLogger("__name__")

# 标准输出
handler1 = logging.StreamHandler()

# 输出到文件
handler2 = logging.FileHandler(filename="test.txt")

logger.setLevel(logging.DEBUG)
handler1.setLevel(logging.WARNING)
handler2.setLevel(logging.DEBUG)

formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
handler1.setFormatter(formatter)
handler2.setFormatter(formatter)

logger.addHandler(handler1)
logger.addHandler(handler2)

logger.debug('This is debug message.')
logger.info('This is info message.')
logger.warning('This is warning message.')
logger.error('This is error message.')
logger.critical('This is critical message.')

如果将日志保存在一个文件中,那么时间一长,或者日志一多,单个日志文件就会很大,既不利于备份,也不利于查看。我们会想到能不能按照时间或者大小对日志文件进行划分呢?答案肯定是可以的。logging.handlers文件中提供了TimedRotatingFileHandlerRotatingFileHandler类分别可以实现按时间和大小划分。

在上面的代码块中修改handler2

1
2
3
4
5
# 每隔500字节保存成一个日志文件,备份文件为3个
handler2 = logging.handlers.RotatingFileHandler("test.txt", mode="w", maxBytes=500, backupCount=3)

# 每隔1个小时,保存一个日志文件,备份文件为3个
handler2 = logging.handlers.TimedRotatingFileHandler("test.txt", when="H", interval=1, backupCount=3)

参考资料

本文链接 https://xugaoxiang.com/2019/08/26/python实用模块推荐(十三)logging/

推荐文章(由hexo文章推荐插件驱动)

使用支付宝打赏
使用微信打赏

请博主喝咖啡!