前面我们需要查看代码信息时,就直接调用print函数在控制台输出,但是实际测试的时候,可能需要大量的调试信息来定位问题,这时候只靠print不能解决根本问题。因此python提供了logging模块,来解决这一问题,接下来我们将围绕logging模块进行讲解。
1.logging类
python的内置日志模块logging提供了通用的日志系统,可以根据测试的需要采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志记录方式。
logging类提供了三个常用的实例类logger,handler,formatter:
实例类 | 实例 | 用法 |
---|---|---|
logger | logger=logging.getLogger(name) | 提供日志接口,如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象。 |
handler | handler=logging.FileHandler(outputname) | 用于将日志记录发送到合适的位置,比如文件,socket等。一个logger对象可以通过addHandler方法添加0到多个handler,每个handler又可以定义不同日志级别,以实现日志分级过滤显示。 |
formatter | formatter=logging.Formatter(’%(asctime)s - %(message)s’) | 指定日志记录输出的具体格式,formatter的构造方法两个必需参数是:消息的格式字符串和日期字符串。 |
2.日志等级设置
在使用logger类中提供了六种不同的日志输出级别,由低到高分别是NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL,如果我们在设置默认格式的时候设置的等级比之后调用的要高,那么调用的logging语句将不会输出;反之,输出时默认等级也会被调用语句的等级覆盖。
1)不设置时,默认格式为WARNING
当我们不调用logger.setLevel(level=logging.DEBUG)设置默认输出等级时,后面直接调用输出日志,我们会发现只能正常输出WARNING、ERROR 和CRITICAL等级的日志,所以当我们不设置默认日志输出等级时,系统默认输出日志等级为WARNING 。
import logging
import sys
def test_log_level():
logger = logging.getLogger() # 获取logger实例
formatter = logging.Formatter("%(asctime)s - %(message)s") # 获取formatter实例
handler = logging.StreamHandler(stream=sys.stdout) # 获取handler实例
handler.setFormatter(formatter)
logger.addHandler(handler)
# 输出日志信息
logger.debug("this is debug")
logger.info("this is info")
logger.warning("this is warning")
logging.error("this is error")
logger.critical("this is critical")
test_log_level()
运行结果:
2021-02-26 16:42:26,478 - this is warning
2021-02-26 16:42:26,478 - this is error
2021-02-26 16:42:26,478 - this is critical
2)设置默认输出等级
当我们调用logger.setLevel(level=logging.INFO)设置默认输出等级时,我们会发现日志等级等于或高于INFO的日志信息都会成功打印 ,而低于默认日志输出等级的日志信息都未打印。
import logging
import sys
def test_log_level():
logger = logging.getLogger() # 获取logger实例
logger.setLevel(logging.INFO) # 设置默认日志输出等级为INFO
formatter = logging.Formatter("%(asctime)s - %(message)s") # 获取formatter实例
handler = logging.StreamHandler(stream=sys.stdout) # 获取handler实例
handler.setFormatter(formatter)
logger.addHandler(handler)
# 输出日志信息
logger.debug("this is debug")
logger.info("this is info")
logger.warning("this is warning")
logging.error("this is error")
logger.critical("this is critical")
test_log_level()
运行结果:
2021-02-26 16:46:33,880 - this is info
2021-02-26 16:46:33,880 - this is warning
2021-02-26 16:46:33,880 - this is error
2021-02-26 16:46:33,880 - this is critical
3.日志输出格式设置
formatter主要用于指定日志记录输出的具体格式,常用的格式为:logging.Formatter(’%(asctime)s - %(name)s -%(levelname)s - %(message)s’)。
常用的日志格式设置有:
格式设置 | 具体含义 |
---|---|
%(name)s | logger的名字,就是logging.getLogger(name)中的name |
%(levelname)s | 文本形式的日志级别,常用为DEBUG和INFO |
%(message)s | 用户输出的消息 |
%(asctime)s | 字符串形式的当前时间。默认格式是 “2021-02-26 16:49:45,896” |
%(levelno)s | 数字形式的日志级别 |
4.简单封装日志类
举例:简单封装一个日志类
封装的日志类,主要包括以下内容:
- 生成的日志文件格式是年月日时分秒.log
- 日志信息分别在控制台和日志文件下输出
- 生成的xxx.log文件存储在项目根目录下Logs文件夹下.
- 这个日志类,支持INFO,ERROR两种日志级别.
- 日志输出格式:时间日期+日志名称+日志级别+日志描述.
import os.path
import logging
import time
class Logger(object):
__handler1 = False
__handler2 = False
def __init__(self):
#日志文件名以当前时间来命名,并存储到项目根目录的Logs文件夹下
lab=time.strftime('%Y%m%d%H%M', time.localtime())
log_path=os.path.dirname(os.path.abspath('.'))+'/Logs/'
outputname=log_path+lab+'.log'
#创建一个handler,用于写入日志文件
self.__handler1=logging.FileHandler(outputname)
self.__handler1.setLevel(level=logging.INFO)
# 再创建一个handler,用于输出到控制台
self.__handler2=logging.StreamHandler()
self.__handler2.setLevel(level=logging.INFO)
#定义handler的输出格式
formatter=logging.Formatter('%(asctime)s - %(name)s -%(levelname)s - %(message)s')
self.__handler1.setFormatter(formatter)
self.__handler2.setFormatter(formatter)
def getInstance(self,loggerName):
# 创建一个logger
logger = logging.getLogger(loggerName)
logger.setLevel(level=logging.DEBUG)
logger.addHandler(self.__handler1)
logger.addHandler(self.__handler2)
return logger
将日志类运用到实例中:
rom time import sleep
from selenium import webdriver
from test.test_logger import Logger
# 输出日志信息的name由logger=来决定
mylogger=Logger().getInstance("test_log")
class testMyLog(object):
def print_log(self):
driver=webdriver.Chrome()
mylogger.info("打开浏览器")
driver.maximize_window()
mylogger.info("最大化浏览器窗口")
driver.implicitly_wait(8)
mylogger.info("隐式等待8秒")
driver.get("https://www.baidu.com")
mylogger.info("打开百度首页。")
sleep(3)
mylogger.info("延时3秒")
driver.quit()
mylogger.info("关闭并退出浏览器")
testMyLog().print_log()
运行结果:
2021-02-26 17:33:52,922 - test_log -INFO - 打开浏览器
2021-02-26 17:33:54,043 - test_log -INFO - 最大化浏览器窗口
2021-02-26 17:33:54,045 - test_log -INFO - 隐式等待8秒
2021-02-26 17:33:55,239 - test_log -INFO - 打开百度首页。
2021-02-26 17:33:58,239 - test_log -INFO - 延时3秒
2021-02-26 17:34:00,786 - test_log -INFO - 关闭并退出浏览器
当getInstance中没有loggerName参数时,logging.getLogger()返回Logger实例,名称是root,即根Logger,此时输出的日志信息中日志名称即为root。
2021-02-26 17:48:25,083 - root -INFO - 打开浏览器
2021-02-26 17:48:26,214 - root -INFO - 最大化浏览器窗口
2021-02-26 17:48:26,217 - root -INFO - 隐式等待8秒
2021-02-26 17:48:27,471 - root -INFO - 打开百度首页。
2021-02-26 17:48:30,481 - root -INFO - 延时3秒
2021-02-26 17:48:33,177 - root -INFO - 关闭并退出浏览器