20_logging日志模块

一、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. 创建日志输出通道。
  2. 设置日志输出渠道等级,等级名称全部要大写。
  3. 将日志输出渠道添加到日志收集器中

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信息

四、日志输出格式

  1. 写明日志格式,用一个字符串代替或者直接在函数中写明格式。
  2. 通过logging模块的Formatter方法设置日志格式
  3. 将日志输出渠道中的日志格式设置为上述日志格式
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))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容