一、logging模块日志级别介绍
日志等级一共分成5个,从低到高分别是:
- DEBUG:输出详细的运行情况,主要用于测试
- INFO:确认一切按预期运行,一般用于输出重要运行情况
- WARNING:一些预料不到的事情发生了,但软件还能按预期工作,在不久的将来会出现问题
- ERROR:发生了错误,软件没能执行某功能,但软件可以继续运行
- CRITICAL:发生了严重的错误,程序本身可能无法继续运行
5个等级分别对应5种打印日志的方法:debug、info、warning、error、critical
二、日志收集器
设置日志收集器的名字和日志收集等级。
- 设置日志收集器的名字:使用logging模块中getLogger方法设置日志名字。
- 设置日志等级:使用logging模块中setLevel方法设置日志等级,等级名称一定要大写
1.不设置日志收集器名字和日志收集等级,日志输出等级默认是WARNING及以上
import logging
# 一
# 日志默认收集等级为:warning及以上(warning、error、critical)
a = 100
print("调试数据", a)
logging.debug("这个是logging模块的调试信息a: {}".format(a))
logging.info("这个是logging模块的调试信息")
logging.warning("这个是logging模块的调试信息")
logging.error("这个是logging模块的调试信息")
logging.critical("这个是logging模块的调试信息")
输出结果如下:
调试数据 100
WARNING:root:这个是logging模块的调试信息
ERROR:root:这个是logging模块的调试信息
CRITICAL:root:这个是logging模块的调试信息
2.不设置日志收集器名字的情况下,设置日志收集等级,日志输出等级跟日志收集等级一致
import logging
# 二
# 不设置日志收集器名字,默认使用root
# 不设置日志收集器名字的情况下,设置日志收集等级,日志输出等级跟日志收集等级一致
log_lev = logging.getLogger()
log_lev.setLevel("DEBUG")
a = 100
print("调试数据", a)
logging.debug("这个是logging模块的调试信息a: {}".format(a))
logging.info("这个是logging模块的调试信息")
logging.warning("这个是logging模块的调试信息")
logging.error("这个是logging模块的调试信息")
logging.critical("这个是logging模块的调试信息")
输出结果如下:
调试数据 100
DEBUG:root:这个是logging模块的调试信息a: 100
INFO:root:这个是logging模块的调试信息
WARNING:root:这个是logging模块的调试信息
ERROR:root:这个是logging模块的调试信息
CRITICAL:root:这个是logging模块的调试信息
3.只设置日志收集器名字和日志收集等级,不设置日志的输出,有一个默认日志输出等级,日志输出等级为warning以上
import logging
# 三
# 日志的收集
# 设置日志收集器,设置日志收集等级
log_lev = logging.getLogger("my_log")
log_lev.setLevel("DEBUG")
# 日志的输出(只设置日志收集器名字和日志收集等级,不设置日志的输出,有一个默认日志输出等级,日志输出等级等级为warning以上)
a = 100
print("调试数据", a)
log_lev.debug("这个是logging模块的debug信息a: {}".format(a))
log_lev.info("这个是logging模块的info信息")
log_lev.warning("这个是logging模块的warning信息")
log_lev.error("这个是logging模块的error信息")
log_lev.critical("这个是logging模块的critical信息")
输出结果如下:
调试数据 100
这个是logging模块的warning信息
这个是logging模块的error信息
这个是logging模块的critical信息
三、日志输出渠道
通过设置日志收集器名字和日志收集等级来收集不同等级的日志,最后设置日志输出渠道来输出不同等级的日志。
- 创建日志输出通道。
- 设置日志输出渠道等级,等级名称全部要大写。
- 将日志输出渠道添加到日志收集器中
1.日志输出到控制台的渠道
import logging
# 四
# 日志的收集
# 设置日志收集器,设置日志收集等级
log_lev = logging.getLogger("my_log")
log_lev.setLevel("DEBUG")
# # 日志的输出(只设置日志的收集,不设置日志的输出,有一个默认日志输出通道,日志输出通道等级为warning以上)
# 创建日志输出通道,设置日志输出通道等级
sh = logging.StreamHandler()
sh.setLevel("DEBUG")
# 将输出渠道添加到日志收集器
log_lev.addHandler(sh)
a = 100
print("调试数据", a)
log_lev.debug("-------------这个是logging模块的debug信息a: {}".format(a))
log_lev.info("这个是logging模块的info信息")
log_lev.warning("这个是logging模块的warning信息")
log_lev.error("这个是logging模块的error信息")
log_lev.critical("这个是logging模块的critical信息")
输出结果如下:
调试数据 100
-------------这个是logging模块的debug信息a: 100
这个是logging模块的info信息
这个是logging模块的warning信息
这个是logging模块的error信息
这个是logging模块的critical信息
2.日志输出到文件的渠道
import logging
# 五
# 日志的收集
# 设置日志收集器,设置日志收集等级
log_lev = logging.getLogger("my_log_2")
log_lev.setLevel("DEBUG")
# 日志输出
# 设置日志输出渠道,设置日志输出渠道等级
sh = logging.StreamHandler()
sh.setLevel("DEBUG")
# 将输出渠道添加到日志收集器
log_lev.addHandler(sh)
# 设置日志输出到文件的渠道,设置日志输出渠道等级
fh = logging.FileHandler(filename="test.log",encoding="utf8")
fh.setLevel("DEBUG")
# 将输出渠道添加到日志收集器
log_lev.addHandler(fh)
a = 100
print("调试数据", a)
log_lev.debug("-------------这个是logging模块的debug信息a: {}".format(a))
log_lev.info("这个是logging模块的info信息")
log_lev.warning("这个是logging模块的warning信息")
log_lev.error("这个是logging模块的error信息")
log_lev.critical("这个是logging模块的critical信息")
输出结果如下:
- 控制台输出结果
调试数据 100
-------------这个是logging模块的debug信息a: 100
这个是logging模块的info信息
这个是logging模块的warning信息
这个是logging模块的error信息
这个是logging模块的critical信息
- 文件内容
-------------这个是logging模块的debug信息a: 100
这个是logging模块的info信息
这个是logging模块的warning信息
这个是logging模块的error信息
这个是logging模块的critical信息
四、日志输出格式
- 写明日志格式,用一个字符串代替或者直接在函数中写明格式。
- 通过logging模块的Formatter方法设置日志格式
- 将日志输出渠道中的日志格式设置为上述日志格式
import logging
# 设置日志收集器,设置日志收集器等级
my_log = logging.getLogger("my_log")
my_log.setLevel("DEBUG")
# 设置日志输出格式
str_form = "%(asctime)s - [%(filename)s - line%(lineno)d] - %(name)s - %(levelname)s: %(message)s"
formater = logging.Formatter(str_form)
# 设置日志输出渠道,设置日志输出渠道等级
sh = logging.StreamHandler()
sh.setLevel("DEBUG")
sh.setFormatter(formater)
# 将输出渠道添加到日志收集器中
my_log.addHandler(sh)
# 设置日志输出到文件的渠道,设置日志输出渠道等级
fh = logging.FileHandler(filename="test.log", encoding="utf8")
fh.setLevel("INFO")
fh.setFormatter(formater)
# 将输出到文件渠道添加到日志收集器中
my_log.addHandler(fh)
a = 100
print("调试数据", a)
my_log.debug("这个是logging模块的debug信息a: {}".format(a))
my_log.info("这个是logging模块的info信息")
my_log.warning("这个是logging模块的warning信息")
my_log.error("这个是logging模块的error信息")
my_log.critical("这个是logging模块的critical信息")
输出结果如下:
2019-11-05 15:35:39,462 - [test_1029_log_format.py - line36] - my_log - DEBUG: 这个是logging模块的debug信息a: 100
调试数据 100
2019-11-05 15:35:39,462 - [test_1029_log_format.py - line37] - my_log - INFO: 这个是logging模块的info信息
2019-11-05 15:35:39,463 - [test_1029_log_format.py - line38] - my_log - WARNING: 这个是logging模块的warning信息
2019-11-05 15:35:39,463 - [test_1029_log_format.py - line39] - my_log - ERROR: 这个是logging模块的error信息
2019-11-05 15:35:39,463 - [test_1029_log_format.py - line40] - my_log - CRITICAL: 这个是logging模块的critical信息
五、封装自己的日志输出类
import logging
class logger(object):
@classmethod
def creat_logger(cls):
# 设置日志收集器,设置日志收集器等级
my_log = logging.getLogger("my_log")
my_log.setLevel("DEBUG")
# 设置日志输出格式
str_form = "%(asctime)s - [%(filename)s - line%(lineno)d] - %(name)s - %(levelname)s: %(message)s"
formater = logging.Formatter(str_form)
# 设置日志输出渠道,设置日志输出渠道等级
sh = logging.StreamHandler()
sh.setLevel("DEBUG")
sh.setFormatter(formater)
# 将输出渠道添加到日志收集器中
my_log.addHandler(sh)
# 设置日志输出到文件的渠道,设置日志输出渠道等级
fh = logging.FileHandler(filename="test.log", encoding="utf8")
fh.setLevel("DEBUG")
fh.setFormatter(formater)
# 将输出到文件渠道添加到日志收集器中
my_log.addHandler(fh)
return my_log
if __name__ == '__main__':
log = logger.creat_logger()
log.info("hello")
输出结果如下:
2019-11-05 15:42:45,070 - [logger.py - line39] - my_log - INFO: hello
六、其他文件调用日志输出方法
第一种
其他文件导入封装日志类,在本文件内创建日志收集器。
import unittest
from register import register
from test_case_read_excel import ReadExcel
from test_project_2.ddt import ddt, data
import logging
from logger import Logger
"""
入参(账号,密码1,密码2) 预期结果
1.正常注册的用例:数据库新用户名python_new,在6-18位之间,两个密码一致,在6-18位之间 {"code": 1, "msg": "注册成功"}
2.注册失败的用例:账号已存在python23 {"code": 0, "msg": "该账户已存在"}
3.注册失败的用例:数据库新用户名python_python_python_new,在6-18之外 {"code": 0, "msg": "账号和密码不在6-18位之间"}
4.注册失败的用例:数据库新用户名python_new,在6-18位之间,两个密码不一致 {"code": 0, "msg": "两次密码不一致"}
5.注册失败的用例:数据库新用户名python_new,在6-18位之间,两个密码一致,在6-18之外 {"code": 0, "msg": "账号和密码不在6-18位之间"}
"""
"""
ddt:
定义:能够实现数据驱动,通过用例数据,自动生成测试用例,过程是自动遍历用例数据,生成测试用例
"""
@ddt
class TestRegister(unittest.TestCase):
# 设置日志收集器,在类外面设置,类的方法里面调用直接调用变量,在类里面设置,类的方法里面调用格式是self.log/类名.log
log = Logger.creat_logger()
read = ReadExcel("cases.xlsx", "testcase")
cases = read.read_data_obj()
@data(*cases)
def test_register(self, case):
"""你好"""
# # 打印case对象的所有属性和属性值
# print(case.__dict__)
# 第一步:准备用例数据(参数和预期结果)
data = eval(case.data)
expected = eval(case.expected)
# 第二步;调用功能函数,获取实际结果
res = register(*data)
# 第三步:比对实际结果和预期结果
try:
self.assertEqual(res, expected)
except AssertionError as e:
self.read.write_data(case.case_id + 1, 5, "未通过")
# TestRegister.log.info("用例({}):执行未通过".format(case.title))
# TestRegister.log.error(e)
self.log.info("用例({}):执行未通过".format(case.title))
self.log.error(e)
raise e
else:
self.read.write_data(case.case_id + 1, 5, "通过")
# TestRegister.log.info("用例({}):执行通过".format(case.title))
self.log.info("用例({}):执行通过".format(case.title))
注意:
- 设置日志收集器,在类外面设置,类的方法里面调用直接调用变量,在类里面设置,类的方法里面调用格式是self.变量名/类名.变量名
- 如果多个文件都创建了日志收集器,日志输出就会执行多次
第二种
在封装日志的文件中直接创建日志收集器,在其他文件调用时,直接导入日志收集器的变量即可。
import logging
class Logger(object):
@classmethod
def creat_logger(cls):
# 设置日志收集器,设置日志收集器等级
my_log = logging.getLogger("my_log")
my_log.setLevel("DEBUG")
# 设置日志输出格式
str_form = "%(asctime)s - [%(filename)s - line%(lineno)d] - %(name)s - %(levelname)s: %(message)s"
formater = logging.Formatter(str_form)
# 设置日志输出渠道,设置日志输出渠道等级
sh = logging.StreamHandler()
sh.setLevel("DEBUG")
sh.setFormatter(formater)
# 将输出渠道添加到日志收集器中
my_log.addHandler(sh)
# 设置日志输出到文件的渠道,设置日志输出渠道等级
fh = logging.FileHandler(filename="test.log", encoding="utf8")
fh.setLevel("DEBUG")
fh.setFormatter(formater)
# 将输出到文件渠道添加到日志收集器中
my_log.addHandler(fh)
return my_log
log = Logger.creat_logger()
if __name__ == '__main__':
log = Logger.creat_logger()
log.info("hello")
import unittest
from register import register
from test_case_read_excel import ReadExcel
from test_project_2.ddt import ddt, data
import logging
from logger import log
"""
入参(账号,密码1,密码2) 预期结果
1.正常注册的用例:数据库新用户名python_new,在6-18位之间,两个密码一致,在6-18位之间 {"code": 1, "msg": "注册成功"}
2.注册失败的用例:账号已存在python23 {"code": 0, "msg": "该账户已存在"}
3.注册失败的用例:数据库新用户名python_python_python_new,在6-18之外 {"code": 0, "msg": "账号和密码不在6-18位之间"}
4.注册失败的用例:数据库新用户名python_new,在6-18位之间,两个密码不一致 {"code": 0, "msg": "两次密码不一致"}
5.注册失败的用例:数据库新用户名python_new,在6-18位之间,两个密码一致,在6-18之外 {"code": 0, "msg": "账号和密码不在6-18位之间"}
"""
"""
ddt:
定义:能够实现数据驱动,通过用例数据,自动生成测试用例,过程是自动遍历用例数据,生成测试用例
"""
@ddt
class TestRegister(unittest.TestCase):
read = ReadExcel("cases.xlsx", "testcase")
cases = read.read_data_obj()
@data(*cases)
def test_register(self, case):
"""你好"""
# # 打印case对象的所有属性和属性值
# print(case.__dict__)
# 第一步:准备用例数据(参数和预期结果)
data = eval(case.data)
expected = eval(case.expected)
# 第二步;调用功能函数,获取实际结果
res = register(*data)
# 第三步:比对实际结果和预期结果
try:
self.assertEqual(res, expected)
except AssertionError as e:
self.read.write_data(case.case_id + 1, 5, "未通过")
log.info("用例({}):执行未通过".format(case.title))
log.error(e)
raise e
else:
self.read.write_data(case.case_id + 1, 5, "通过")
log.info("用例({}):执行通过".format(case.title))