关键词搜索

源码搜索 ×
×

Python 日志打印之logging.config.dictConfig使用总结

发布2021-01-18浏览2111次

详情内容

#实践环境

WIN 10

Python 3.6.5

#函数说明

logging.config.dictConfig(config)

dictConfig函数位于logging.config模块,该函数通过字典参数config对logging进行配置。3.2版本新增的函数

##参数说明

config 字典类型,包含以下key:

version - 表示版本,该键值为从1开始的整数。该key必选,除此之外,其它key都是可选。

formatters - 日志格式化器,其value值为一个字典,该字典的每个键值对都代表一个Formatter,键值对中,key代表Formatter ID(自定义ID),value为字典,描述如何配置相应的Formatter实例。默认格式为 ‘%(message)s’

filters - 日志过滤器,其value值为一个字典,该字典的每个键值对都代表一个Filter,键值对中,key代表Filter ID(自定义ID),value为字典,描述如何配置相应的Filter实例。

handlers - 日志处理器,其value值为一个字典,该字典的每个键值对都代表一个Handler,键值对中,key代表Handler ID(自定义ID),value为字典,描述如何配置相应的Handler实例,包含以下配置key:

class (必选). 日志处理器类全称
level (可选). 指定该日志处理器需要处理哪些级别的日志,低于该级别的日志将不被该handler处理。level可以为代表日志级别的整数或者表大写字符串,字符串日志级别和数字日志级别对应关系如下:

    CRITICAL = 50

    FATAL = CRITICAL

    ERROR = 40

    WARNING = 30

    WARN = WARNING

    INFO = 20

    DEBUG = 10

    NOTSET = 0

    下同,不再赘述.

    formatter (可选). 指定该日志处理器使用的日志格式化器
    filters (可选). 制定该日志处理器使用的日志过滤器

    上述的class配置项的值,可以使用自定义Handler类,此时,如果自定义Handler类的__init__构造函数还需要其它参数来初始化类实例,可以继续添自定义参数,这些自定义参数被当做关键字参数会自动传递给构造函数。

    一个例子:

    "handlers": {
        "console":{
            "class":"study.MyLogHandler",
            "formatter":"brief",
            "level":"INFO"
        },
        "file": {
            "class": "logging.handlers.RotatingFileHandler",
            "formatter": "precise",
      "filename": "logconfig.log",
      "maxBytes": 1024,
      "backupCount": 3
        }
    }
      
    

      id为console的日志处理器被实例化为一个logging.StreamHandler,使用sys.stout作为基础实例流。id为file的日志处理器则被实例化为具有关键字参数filename =‘logconfig.log’,maxBytes = 1024,backupCount = 3的 logging.handlers.RotatingFileHandler

      loggers - 日志记录器,其value值为一个字典,该字典的每个键值对都代表一个Handler,键值对中,key代表Handler ID,value为字典,描述如何配置相应的Logger实例,包含以下配置key:

      level (可选). 指定该日志记录器需要记录哪些级别的日志,低于该python基础教程级别的日志将不被该logger记录。
      propagate (可选). 指定该日志记录器的propagation配置,为布尔值,即True 或 False,用于控制是否向上遍历父辈日志打印器,进而控制当前日志打印器是否共享父辈打印器的日志处理器。True,向上遍历,否则不向上遍历。
      filters (可选). 指定该日志记录器使用的日志过滤器
      handlers (可选). 制定该日志记录器使用的日志处理器

      root - root logger配置。除了不支持propagate配置项以外,该配置的处理过程同处理其它logger的配置一样,配置规则也一样

      incremental - 用于判断该config配置是否解释为现有配置的增量配置,还是覆盖原有配置。默认为False,即使用现有fileConfig()API使用的相同语义替换现有配置

      disable_existing_loggers - 其value为布尔值,表示是否禁用现有日志记录器(root logger除外),默认值为True,即禁用。如果incremental 键值为True,则忽略该配置项

      #代码示例1

      study.py

      study.py

      #!/usr/bin/env python
      # -*- coding:utf-8 -*-
       
       
      '''
      @CreateTime: 2020/12/29 14:08
      @Author : shouke
      '''
       
      import logging
      import logging.config
       
      LOGGING_CONFIG = {
          "version": 1,
          "formatters": {
              "default": {
                  'format':'%(asctime)s %(filename)s %(lineno)s %(levelname)s %(message)s',
              },
              "plain": {
                  "format": "%(message)s",
              },
          },
          "handlers": {
              "console": {
                  "class": "logging.StreamHandler",
                  "level": "INFO",
                  "formatter": "default",
              },
              "console_plain": {
                  "class": "logging.StreamHandler",
                  "level":logging.INFO,
                  "formatter": "plain"
              },
              "file":{
                  "class": "logging.FileHandler",
                  "level":20,
                  "filename": "./log.txt",
                  "formatter": "default",
              }
          },
          "loggers": {
              "console_logger": {
                  "handlers": ["console"],
                  "level": "INFO",
                  "propagate": False,
              },
              "console_plain_logger": {
                  "handlers": ["console_plain"],
                  "level": "DEBUG",
                  "propagate": False,
              },
              "file_logger":{
                  "handlers": ["file"],
                  "level": "INFO",
                  "propagate": False,
              }
          },
          "disable_existing_loggers": True,
      }
       
      # 运行测试
      logging.config.dictConfig(LOGGING_CONFIG)
      logger = logging.getLogger("console_logger")
      logger.debug('debug message')
      logger.info('info message')
      logger.warn('warning message')
      logger.error('error message')
      logger.critical('critical message')
      
        16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68

      运行study.py,结果输出如下

      2021-01-09 10:01:59,123 study.py 66 INFO info message

      2021-01-09 10:01:59,123 study.py 67 WARNING warning message

      2021-01-09 10:01:59,123 study.py 68 ERROR error message

      2021-01-09 10:01:59,123 study.py 69 CRITICAL critical message

      #代码示例2

      基于代码示例1,修改LOGGING_CONFIG及getLogger函数参数

      LOGGING_CONFIG = {
          "version": 1,
          "formatters": {
              "default": {
                  'format':'%(asctime)s %(filename)s %(lineno)s %(levelname)s %(message)s',
              }
          },
          "handlers": {
              "console": {
                  "class": "logging.StreamHandler",
                  "level": "INFO",
                  "formatter": "default",
              }
          },
          "disable_existing_loggers": True,
          "root": {
              "handlers": ["console"],
              "level": "DEBUG"
          },
      }
       
      # 运行测试
      logging.config.dictConfig(LOGGING_CONFIG)
      logger = logging.getLogger("root")
      logger.debug('debug message')
      logger.info('info message')
      logger.warn('warning message')
      logger.error('error message')
      logger.critical('critical message')
        
      
        16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30

      运行study.py,结果输出如下

      2021-01-09 10:33:03,456 study.py 38 INFO info message

      2021-01-09 10:33:03,456 study.py 39 WARNING warning message

      2021-01-09 10:33:03,456 study.py 40 ERROR error message

      2021-01-09 10:33:03,456 study.py 41 CRITICAL critical message

      源码的角度分析propagate配置项

      Logger类,位于logging/init.py

      class Logger(Filterer): 
          #...略 
       
          def debug(self, msg, *args, **kwargs):
              """
              Log 'msg % args' with severity 'DEBUG'.
       
              To pass exception information, use the keyword argument exc_info with
              a true value, e.g.
       
              logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
              """
              if self.isEnabledFor(DEBUG):
                  self._log(DEBUG, msg, args, **kwargs)
       
          def info(self, msg, *args, **kwargs):
              """
              Log 'msg % args' with severity 'INFO'.
       
              To pass exception information, use the keyword argument exc_info with
              a true value, e.g.
       
              logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
              """
              if self.isEnabledFor(INFO):
                  self._log(INFO, msg, args, **kwargs)
           
          #...略
       
          def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):
              """
              Low-level logging routine which creates a LogRecord and then calls
              all the handlers of this logger to handle the record.
              """
              sinfo = None
              if _srcfile:
                  #IronPython doesn't track Python frames, so findCaller raises an
                  #exception on some versions of IronPython. We trap it here so that
                  #IronPython can use logging.
                  try:
                      fn, lno, func, sinfo = self.findCaller(stack_info)
                  except ValueError: # pragma: no cover
                      fn, lno, func = "(unknown file)", 0, "(unknown function)"
              else: # pragma: no cover
                  fn, lno, func = "(unknown file)", 0, "(unknown function)"
              if exc_info:
                  if isinstance(exc_info, BaseException):
                      exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
                  elif not isinstance(exc_info, tuple):
                      exc_info = sys.exc_info()
              record = self.makeRecord(self.name, level, fn, lno, msg, args,
                                       exc_info, func, extra, sinfo)
              self.handle(record)
       
          def handle(self, record):
              """
              Call the handlers for the specified record.
       
              This method is used for unpickled records received from a socket, as
              well as those created locally. Logger-level filtering is applied.
              """
              if (not self.disabled) and self.filter(record):
                  self.callHandlers(record)
       
       
          def hasHandlers(self):
              """
              See if this logger has any handlers configured.
       
              Loop through all handlers for this logger and its parents in the
              logger hierarchy. Return True if a handler was found, else False.
              Stop searching up the hierarchy whenever a logger with the "propagate"
              attribute set to zero is found - that will be the last logger which
              is checked for the existence of handlers.
              """
              c = self
              rv = False
              while c:
                  if c.handlers:
                      rv = True
                      break
                  if not c.propagate:
                      break
                  else:
                      c = c.parent
              return rv
       
       
          def callHandlers(self, record):
              """
              Pass a record to all relevant handlers.
       
              Loop through all handlers for this logger and its parents in the
              logger hierarchy. If no handler was found, output a one-off error
              message to sys.stderr. Stop searching up the hierarchy whenever a
              logger with the "propagate" attribute set to zero is found - that
              will be the last logger whose handlers are called.
              """
              c = self
              found = 0
              while c:
                  for hdlr in c.handlers:
                      found = found + 1
                      if record.levelno >= hdlr.level:
                          hdlr.handle(record)
                  if not c.propagate:
                      c = None    #break out
                  else:
                      c = c.parent
              if (found == 0):
                  if lastResort:
                      if record.levelno >= lastResort.level:
                          lastResort.handle(record)
                  elif raiseExceptions and not self.manager.emittedNoHandlerWarning:
                      sys.stderr.write("No handlers could be found for logger"
                                       " \"%s\"\n" % self.name)
                      self.manager.emittedNoHandlerWarning = True
        
      
        16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
      • 102
      • 103
      • 104
      • 105
      • 106
      • 107
      • 108
      • 109
      • 110
      • 111
      • 112
      • 113
      • 114
      • 115
      • 116
      • 117
      • 118

      默认的,当通过logger.debug,logger.info的方式打印c#教程日志时,会先判断对应日志级别是否开启,如果开启,则调用logger实例的_log方法,接着经过一连串的函数调用(self._log() -> self.handle -> self.callHandlers),如上,self.callHandlers中,会先遍历当前日志打印器自身的所有日志处理器,处理日志消息,然后判断propagate属性是否为True,如果为True,则获取上级日志打印器,继续遍历其日志处理器,处理消息,否则不遍历上级

      另外,查看hasHandlers函数可知,判断一个logger是否有日志处理器,也用到了propagate,如果propagate为True,则遍历父级日志打印器,看其是否存在日志处理器,如果父级或者父辈日志打印器存在日志处理器,则判断该logger拥有日志处理器。

      由此可见,propagate功能就是用于控制是否向上遍历父辈日志打印器,进而控制当前日志打印器是否共享父辈打印器的日志处理器。

      作者:授客
      本文版权归原作者所有,仅供学习参考之用,转载vb.net教程

      请注明出处:https://www.cnblogs.com/shouke/p/14256086.html,未经作者允许请务必保留此段声明!

      Git地址:https://gitee.com/ishouke

      相关技术文章

      点击QQ咨询
      开通会员
      返回顶部
      ×
      微信扫码支付
      微信扫码支付
      确定支付下载
      请使用微信描二维码支付
      ×

      提示信息

      ×

      选择支付方式

      • 微信支付
      • 支付宝付款
      确定支付下载