日志是一种可以追踪某些软件运行时所发生事件的方法。一个完整的程序离不开日志,无论是开发阶段、测试阶段,还是运行阶段,我们都可以通过日志查看程序的运行情况,或是在出现故障时快速定位问题。
logging库
logging库是Python的一个标准库,该标准库提供日志记录API,可用于实现日志记录功能。我们可以将自己的日志信息与来自该库的信息整合起来。
logging日志等级
logging库默认定义了几个日志等级,如表4-2所示,它允许开发人员自定义其日志等级。
表4-2logging日志等级
表4-2中的日志等级从上到下依次升高,即DEBUG<INFO<WARNING<ERROR<CRITICAL,而日志记录的信息量是依次减少的。
当指定一个日志等级,程序只会记录大于或等于这个日志等级的日志信息,例如设置打印INFO,那么比INFO等级高的WARNING、ERROR和CRITICAL等级的信息都将被打印。
logging四大组件
logging库使用的时候涉及四大组件,如表4-3所示。
表4-3logging四大组件
这件组件之间的关系描述如下。
日志器需要通过处理器将日志信息输出到不同的目标位置,如文件、sys.stdout、网络等。
不同的处理器可以将日志输出到不同的位置。
每个处理器都可以设置自己的过滤器实现日志过滤,从而只保留感兴趣的日志。
每个处理器都可以设置自己的格式器实现同一条日志以不同的格式输出到不同的地方。
简单来说,日志器只是入口,真正工作的是处理器,处理器还可以通过过滤器和格式器对要输出的日志内容做过滤和格式化等处理。最后,处理器负责发送相关的信息到目的地。
有些处理器可以把信息输出到控制台,有些处理器可以把信息输出到文件,还有些处理器可以把信息发送到网络上,如表4-4所示。如果觉得不够用,我们还可以编写自己的处理器。
表4-4常用的处理器
每个处理器都可以设置自己的格式器规定同一条日志记录哪些字段内容信息,我们可以根据自己的需求定义日志格式,常见的日志格式符号如表4-5所示。
表4-5常用的日志格式符号
封装示例
在这里,我们封装一个简单的日志类,方便以后在不同项目中重复使用,示例主要是实现了如下两个需求,供大家学习借鉴。
生成的日志文件格式是:年月日_模块名.log。
生成的×××.log文件存储在项目的根目录中的logs文件夹下,all_logs文件夹记录所有等级的日志信息,err_logserr_logs文件夹只记录ERROR等级的日志信息。
首先,新建一个工程MyLogUtils,然后新建logs文件夹,并在logs文件夹中依次建立all_logs、err_logs两个文件夹,如图4-1所示。
图4-1项目结构
封装的loggerutil工具类放在mylogger文件夹下,具体代码如代码清单4-3所示。
# -*- coding: utf-8 -*-
# @Time : 2022/4/17 5:21 下午
# @Project : MyLogUtils
# @File : loggerutil.py
# @Author : hutong
# @Describe: 微信公众号:大话性能
# @Version: Python3.9.8
import logging
import os.path
import logging.handlers
from Settings import SettingConf
setting = SettingConf() # 从配置文件中读取配置
# 封装日志
class Mylogger(object):
def __init__(self, loggerName=None, fileName='operation.log'):
"""
指定保存日志的文件路径,日志等级 """
# 创建一个日志器
self.logger = logging.getLogger(loggerName)
self.logger.setLevel(logging.DEBUG)
# 日志名称,带有路径的全路径文件名
self.log_name = setting.log_prefix + fileName
# print(os.path.dirname(os.getcwd()))
# 创建一个处理器,用于写入日志文件(每天生成1个,保留30天的日志)
# fh = logging.handlers.TimedRotatingFileHandler(self.log_name, 'D', 1, 30)
# 创建一个处理器,写入所有日志
all_fh = logging.FileHandler(self.log_name, mode='a+', encoding='utf-8')
all_fh.setLevel(logging.INFO)
# 创建一个处理器,写入错误日志
# err_fh = logging.FileHandler(self.error_log_name, mode='a+', encoding='utf-8')
# err_fh.setLevel(logging.ERROR)
# 创建一个处理器,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# 定义处理器的输出格式
# 以时间-日志器名称-日志等级-日志内容的形式展示
all_formatter = logging.Formatter(
'[%(asctime)s] - [%(levelname)s]
line:%(lineno)d %(filename)s;%(module)s->%(funcName)s %(message)s')
# ERROR等级日志记录的输出格式
# err_formatter = logging.Formatter(
# '[%(asctime)s] - %(filename)s:%(module)s->%(funcName)s line:%(lineno)d
[%(levelname)s] %(message)s')
all_fh.setFormatter(all_formatter)
# err_fh.setFormatter(err_formatter)
# ch.setFormatter(err_formatter)
# 给logger添加handler
self.logger.addHandler(all_fh)
# self.logger.addHandler(err_fh)
self.logger.addHandler(ch)
all_fh.close()
# err_fh.close()
ch.close()
def __str__(self):
return "logger为: %s,日志文件名为: %s" % (
self.logger,
self.log_name,
)
def getlog(self):
return self.logger
if __name__ == "__main__":
Mylogger().getlog().info(
'1111111'
)
代码清单4-3loggerutil
测试日志文件输出,我们发现logs文件夹下生产的日志满足要求,其中all_logs文件夹下的文件里记录了INFO和ERROR等级的日志,而err_logs文件夹下的文件里只记录了ERROR等级的日志。
上面的封装比较简单,这里只是抛砖引玉,大家可以根据自己的需求,封装自己的日志操作类。
提示
Python的日志管理除了可以用自带的logging库,还可以用第三方的loguru库。loguru的用法非常简单,loguru中有且仅有一个对象logger,所以loguru可以在多个Python文件中使用,而且不会出现冲突。
loguru默认配置了一套日志输出格式,有时间、等级、模块名、行号和日志信息,不需要提前配置或手动创建logger对象,直接使用即可。另外,loguru的输出是彩色的,界面更加友好。
在使用logging库时,我们需要手动配置处理器、格式器和过滤器,需要调用不同的函数完成其他配置,但是在使用loguru时,我们只需要实现一个add()即可。通过add(),我们可以设置处理器、格式器、过滤器信息和日志等级。
除了常见的创建记录日志文件,rotation滚动记录日志文件,retention指定日志保留时长,以及compression配置文件压缩格式,loguru还支持在多模块的情况下使用,并且在多线程下,loguru也是安全的。
最后:下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。