欢迎访问我的网站,希望内容对您有用,感兴趣的可以加入我们的社群。

Python实用模块(十四)logging

实用模块 迷途小书童 5年前 (2019-12-04) 7103次浏览 0个评论

软硬件环境

  • 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

代码实践


# 导入模块
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文件内容为

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对象,示例代码如下

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

# 每隔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)

参考资料

喜欢 (0)

您必须 登录 才能发表评论!