zoukankan      html  css  js  c++  java
  • 03-logging日志

    logging模块的日志,我们需要明白四个内容:

    1. 日志收集器
    2. 日志级别
    3. 输出渠道
    4. 日志内容

    1. 日志的级别

    logging模块中,对日志的输出级别有着划分,分别是:DEBUG/INFO/WARNING/ERROR/CRITICAL这五种级别。

    如果你想要设置你的日志输出级别是DEBUG,那么logging模块会全面输入所有的日志;如果设置的日志输出级别是INFO,那么只会输出级别在INFO及以上的日志内容;其余的日志级别输出也是一样的。

    2. 日志收集器:自定义个人的日志收集器

    日志收集器是用来收集日志并输出的,logging中有一个默认的日志收集器,这个默认的日志收集器设置的日志的输出级别是WARNING级别,并且日志的名字是root,输出的格式也是一个默认的格式。

    也就是说,如果你的日志级别是INFO默认的日志收集器是不会输出日志的。

    import logging
    logging.warning("哈哈") # WARNING:root:哈哈
    
    2.1 创建日志收集器
    import logging
    
    # 传入一个名字,作为这个日志收集器的名字
    logger = logging.getLogger("admin")
    

    此时,这个日志收集器没有日志级别,没有输出渠道,没有输出的日志内容格式。

    所以我们需要去设置这些内容。

    2.2 设置日志级别
    import logging
    
    # 创建一个日志收集器
    logger = logging.getLogger("admin")
    
    # 设置输出级别
    logger.setLevel(logging.DEBUG)
    

    定义日志级别的时候,调用setLevel()方法,并传入日志的级别。

    日志级别在logging模块中有专门的常量,用来设置日志级别:

    logging.DEBUG
    logging.INFO
    logging.WARNING
    logging.ERROR
    logging.CRITICAL
    

    设置了日志的级别,但是依然输出不了任何的日志,因为没有设置日志的输出的渠道。

    2.3 设置输出渠道

    日志的输出渠道有两种,一个是控制台输出,一个是文件输出。

    控制台输出:logging.StreamHandler()

    文件输出:logging.FileHandler(filepath)。文件输出路径需要传递一些参数,例如文件路径,编码格式等。

    2.4 设置输出格式

    输出格式在logging的源码中,给出了输出的内容信息:

    %(name)s	        日志收集器的名字
    %(levelno)s	        数字形式的日志级别
    %(levelname)s	    文本形式的日志级别
    %(pathname)s	    调用日志输出函数的模块的完整路径名,可能没有
    %(filename)s	    调用日志输出函数的模块的文件名
    %(module)s	        调用日志输出函数的模块名
    %(funcName)s	    调用日志输出函数的函数名
    %(lineno)d	        调用日志输出函数的语句所在的代码行
    %(created)f	        当前时间,用UNIX标准的表示时间的浮 点数表示
    %(relativeCreated)d	输出日志信息时的,自Logger创建以 来的毫秒数
    %(asctime)s	        字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    %(thread)d	        线程ID。可能没有
    %(threadName)s	    线程名。可能没有
    %(process)d	        进程ID。可能没有
    %(message)s	        用户输出的消息
    

    设置输出格式:

    fmt = "%(asctime)s %(name)s  %(levelname)s %(filename)s %(lineno)d line %(message)s"
    fortmatter = logging.Formatter(fmt)
    
    2.5 将输出渠道与输出格式进行绑定
    handle = logging.StreamHandler() # 控制台输出
    # logging.FileHandler()   # 文件输出
    
    # 设置输出格式
    fmt = "%(asctime)s %(name)s  %(levelname)s %(filename)s %(lineno)d line %(message)s"
    fortmatter = logging.Formatter(fmt)
    
    # 将输出渠道和输出格式绑定
    handle.setFormatter(fortmatter)
    
    2.6 将输出渠道添加到日志收集器中
    # 设置输出渠道
    handle = logging.StreamHandler() # 控制台输出
    # logging.FileHandler()   # 文件输出
    
    # 设置输出格式
    fmt = "%(asctime)s %(name)s  %(levelname)s %(filename)s %(lineno)d line %(message)s"
    fortmatter = logging.Formatter(fmt)
    
    # 将输出渠道和输出格式绑定
    handle.setFormatter(fortmatter)
    
    # 将设置好的渠道,添加到日志收集器中,完成自定义日志收集器
    logger.addHandler(handle)
    

    这里指的是已经设置好输出格式的输出渠道,将这歌输出渠道添加到日志收集器中,这个自定义的日志收集器就设置好了。

    完整代码:

    import logging
    
    # logging.warning("哈哈")
    
    # 创建一个日志收集器
    logger = logging.getLogger("admin")
    
    # 设置输出级别
    logger.setLevel(logging.DEBUG)
    
    # 设置输出渠道
    handle = logging.StreamHandler() # 控制台输出
    # logging.FileHandler()   # 文件输出
    
    # 设置输出格式
    fmt = "%(asctime)s %(name)s  %(levelname)s %(filename)s %(lineno)d line %(message)s"
    fortmatter = logging.Formatter(fmt)
    
    # 将输出渠道和输出格式绑定
    handle.setFormatter(fortmatter)
    
    # 将设置好的渠道,添加到日志收集器中,完成自定义日志收集器
    logger.addHandler(handle)
    
    logger.debug("haha")
    
    

    同一个日志收集器可以有多个输出渠道,并且每个输出渠道的输出日志级别都可以不相同。

    2.7 对渠道的输出级别进行调控

    当设置了一个输出渠道,那么就可以单独对这个输出渠道进行设置输出的 日志级别。

    但是设置的输出级别,是不能超过自定义的日志收集器的输出级别的。

    # 设置输出渠道
    handle = logging.StreamHandler() # 控制台输出
    # logging.FileHandler()   # 文件输出
    handle.setLevel(logging.INFO)
    

    这样一来,在控制台中,就只会输出INFO级别的日志。

    封装一个属于自己的日志类:

    import logging
    
    
    class MyLogger(object):
    
        def __init__(self, filename=None, level=logging.DEBUG):
            # 初始化一个日志收集器
            self.logger = logging.getLogger("admin")
            # 初始化日志输出格式
            self.fmt = "%(asctime)s %(name)s  %(levelname)s %(filename)s-%(lineno)d line %(message)s"
            # 设置日志收集器级别
            self.logger.setLevel(level)
            self.level = level
            self.filename = filename
            self.handle = None
    
        def private_logger(self, level, msg):
            # 设置输出渠道
            if self.filename:
                self.handle = logging.FileHandler(self.filename, encoding="utf-8")
            else:
                self.handle = logging.StreamHandler()
            # 设置输出格式
            formatter = logging.Formatter(self.fmt)
            # 日志收集器与输出格式绑定
            self.handle.setFormatter(formatter)
            # 将 输出渠道添加到日志收集器中
            self.logger.addHandler(self.handle)
            # 使用反射原理,执行日志输出
            if hasattr(self, level):
                func = getattr(self, level)
                func(msg)
            # 移除添加的输出handle:在执行测试用例的时候,都会调用一次private_logger,而此时每一个logger中都已经有了一个handle,所以重复调用private_logger都会重复向同一个logger中添加同样的handle,造成日志输出重复。
            # 所以需要在private_logger函数的末尾处,移除handle来防止日志重复。
            self.logger.removeHandler(self.handle)
    
        def debug(self, msg):
            self.logger.debug(msg)
    
        def info(self, msg):
            self.logger.info(msg)
    
        def warning(self, msg):
            self.logger.warning(msg)
    
        def error(self, msg):
            self.logger.error(msg)
    
        def critical(self, msg):
            self.logger.critical(msg)
    
        def exception(self, msg):
            self.logger.exception(msg)
    
    logger = MyLogger()
    logger.private_logger("exception", "断言失败")
    # logger.exception()
    
    
    
    

    封装自定义日志类可能出现的问题

    1. 重复输出日志

    日志重复输出:Python Logging日志重复输出问题

    这是因为在执行测试用例的时候,每一次调用封装的日志类,都会在同一个logger中多次添加同一个handle,造成日志输出重复。

    所以在每次执行测试用例之前,都需要先移除logger中已有的handle,再去重新添加handle来防止日志输出重复。

  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/Pilaoban/p/13173078.html
Copyright © 2011-2022 走看看