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

By:授客 QQ:1033553122

#实践环境

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__构造函数还需要其它参数来初始化类实例,可以继续添自定义参数,这些自定义参数被当做关键字参数会自动传递给构造函数。

一个例子:

  1. "handlers": {
  2. "console":{
  3. "class":"study.MyLogHandler",
  4. "formatter":"brief",
  5. "level":"INFO"
  6. },
  7. "file": {
  8. "class": "logging.handlers.RotatingFileHandler",
  9. "formatter": "precise",
  10. "filename": "logconfig.log",
  11. "maxBytes": 1024,
  12. "backupCount": 3
  13. }
  14. }

  

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 (可选). 指定该日志记录器需要记录哪些级别的日志,低于该级别的日志将不被该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

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

  

运行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函数参数

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

  

运行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

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

  

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

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

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

Python 日志打印之logging.config.dictConfig使用总结的更多相关文章

  1. python 日志打印之logging使用介绍

    python 日志打印之logging使用介绍 by:授客QQ:1033553122 测试环境: Python版本:Python 2.7   简单的将日志打印到屏幕 import logging lo ...

  2. Python 日志打印之logging.getLogger源码分析

    日志打印之logging.getLogger源码分析 By:授客 QQ:1033553122 #实践环境 WIN 10 Python 3.6.5 #函数说明 logging.getLogger(nam ...

  3. Python 日志打印之自定义logger handler

    日志打印之自定义logger handler By:授客 QQ:1033553122 #实践环境 WIN 10 Python 3.6.5 #实践代码 handler.py #!/usr/bin/env ...

  4. python(36):python日志打印,保存,logging模块学习

    1.简单的将日志打印到屏幕 import logging logging.debug('This is debug message') logging.info('This is info messa ...

  5. Python——日志模块(logging)

    一.日志说明 日志是跟踪软件运行时所发生的事件的一种方法.软件开发者在代码中调用日志函数,表明发生了特定的事件.事件由描述性消息描述,该描述性消息可以可选地包含可变数据(即,对于事件的每次出现都潜在地 ...

  6. 『无为则无心』Python日志 — 67、logging日志模块处理流程

    目录 1.概括理解 2.详细说明 3.应用示例 1.概括理解 了解了四大组件的基本定义之后,我们通过图示的方式来理解下信息的传递过程: 也就是获取的日志信息,进入到Logger日志器中,传递给处理器确 ...

  7. Python日志记录(logging)

    import logging logfile = 'e:\\a.txt' # logging.basicConfig(filename=logfile,level=logging.INFO) # lo ...

  8. python基础--包、logging、hashlib、openpyxl、深浅拷贝

    包:它是一系列模块文件的结合体,表现形式就是一个文件夹,该文件夹内部通常会有一个__init__.py文件,包的本质还是一个模块. 首次导入包:(在导入语句中中 . 号的左边肯定是一个包(文件夹)) ...

  9. 以打印日志为荣之logging模块详细使用

    啄木鸟社区里的Pythonic八荣八耻有一条: 以打印日志为荣 , 以单步跟踪为耻; 很多程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误.警告等信息输出,python ...

随机推荐

  1. 百度网盘下载器:SpeedPan2.3.8

    SpeedPan是款百度网盘资源下载工具,下载速度还行(至少比百度网盘快太多了),支持登录百度账号,也支持免登录下载.官网免费版的取消分享了,我从油管上看到了这个软件,分享给大家. 天翼云:https ...

  2. js原生方法reduce实现

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Pytorch训练时显存分配过程探究

    对于显存不充足的炼丹研究者来说,弄清楚Pytorch显存的分配机制是很有必要的.下面直接通过实验来推出Pytorch显存的分配过程. 实验实验代码如下: import torch from torch ...

  4. OpenCV Error: Assertion failed (src.size == dst.size && src.channels() == dst.channels()) in cvConvertScale

    发现问题:在做kinect采集的深度图去噪的时候遇到了cvConvertScale格式转换的问题. OpenCV Error: Assertion failed (src.size == dst.si ...

  5. C#9.0新特性详解系列之六:增强的模式匹配

    自C#7.0以来,模式匹配就作为C#的一项重要的新特性在不断地演化,这个借鉴于其小弟F#的函数式编程的概念,使得C#的本领越来越多,C#9.0就对模式匹配这一功能做了进一步的增强. 为了更为深入和全面 ...

  6. 精尽Spring MVC源码分析 - 一个请求的旅行过程

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  7. Kubernetes K8S之鉴权RBAC详解

    Kubernetes K8S之鉴权概述与RBAC详解 K8S认证与授权 认证「Authentication」 认证有如下几种方式: 1.HTTP Token认证:通过一个Token来识别合法用户. H ...

  8. SpringBoot异步调用--@Async详解

    1. 概述   在日常开发中,为了提高主线程的效率,往往需要采用异步调用处理,例如系统日志等.在实际业务场景中,可以使用消息中间件如RabbitMQ.RocketMQ.Kafka等来解决.假如对高可用 ...

  9. 安卓和ios的app证书过期的相关问题汇总

    一,ios的APP的发布流程请见:ios的APP的发布流程 http://www.jianshu.com/p/b1b77d804254 这篇文章写得很好很全面 二,app证书过期了怎么办: IOS的情 ...

  10. [水题日常]Luogu1113 杂务

    这几天又在颓. 我的blog难度目前还比较低,主要面向像我这样子的新手(当然内容也会尽量讲得具体清楚一些)x 如果有错误还请指出~ 写完随笔之后才去翻了一下这题题解之后才注意到这题是有序的 QAQ完全 ...