Python 日志打印之logging.config.dictConfig使用总结
日志打印之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__构造函数还需要其它参数来初始化类实例,可以继续添自定义参数,这些自定义参数被当做关键字参数会自动传递给构造函数。
一个例子:
"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 (可选). 指定该日志记录器需要记录哪些级别的日志,低于该级别的日志将不被该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')
运行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')
运行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
默认的,当通过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使用总结的更多相关文章
- python 日志打印之logging使用介绍
python 日志打印之logging使用介绍 by:授客QQ:1033553122 测试环境: Python版本:Python 2.7 简单的将日志打印到屏幕 import logging lo ...
- Python 日志打印之logging.getLogger源码分析
日志打印之logging.getLogger源码分析 By:授客 QQ:1033553122 #实践环境 WIN 10 Python 3.6.5 #函数说明 logging.getLogger(nam ...
- Python 日志打印之自定义logger handler
日志打印之自定义logger handler By:授客 QQ:1033553122 #实践环境 WIN 10 Python 3.6.5 #实践代码 handler.py #!/usr/bin/env ...
- python(36):python日志打印,保存,logging模块学习
1.简单的将日志打印到屏幕 import logging logging.debug('This is debug message') logging.info('This is info messa ...
- Python——日志模块(logging)
一.日志说明 日志是跟踪软件运行时所发生的事件的一种方法.软件开发者在代码中调用日志函数,表明发生了特定的事件.事件由描述性消息描述,该描述性消息可以可选地包含可变数据(即,对于事件的每次出现都潜在地 ...
- 『无为则无心』Python日志 — 67、logging日志模块处理流程
目录 1.概括理解 2.详细说明 3.应用示例 1.概括理解 了解了四大组件的基本定义之后,我们通过图示的方式来理解下信息的传递过程: 也就是获取的日志信息,进入到Logger日志器中,传递给处理器确 ...
- Python日志记录(logging)
import logging logfile = 'e:\\a.txt' # logging.basicConfig(filename=logfile,level=logging.INFO) # lo ...
- python基础--包、logging、hashlib、openpyxl、深浅拷贝
包:它是一系列模块文件的结合体,表现形式就是一个文件夹,该文件夹内部通常会有一个__init__.py文件,包的本质还是一个模块. 首次导入包:(在导入语句中中 . 号的左边肯定是一个包(文件夹)) ...
- 以打印日志为荣之logging模块详细使用
啄木鸟社区里的Pythonic八荣八耻有一条: 以打印日志为荣 , 以单步跟踪为耻; 很多程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误.警告等信息输出,python ...
随机推荐
- 推荐系统实践 0x0c FM系列
逻辑回归(LR) 在介绍FM系列之前,我想首先简单介绍一下逻辑回归.通常来说,逻辑回归模型能够综合利用更多的信息,如用户.物品.上下文等多种不同的特征,生成更为全面的结果.另外,逻辑回归将推荐问题看成 ...
- .NET 开源导入导出库 Magicodes.IE 2.5发布
今天我们发布了2.5版本,这当然也离不开大家对Magicodes.IE的支持,今天我也是跟往常一样列举了该版本一些重要的更新内容. 当然也要说一下,在这个版本中我们设计了全新的LOGO Excel导出 ...
- LeetCode初级算法之数组:136 只出现一次的元素
只出现一次的元素 题目地址:https://leetcode-cn.com/problems/single-number/ 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找 ...
- 【题解】P2610 [ZJOI2012]旅游
link 题意 T国的国土可以用一个凸N边形来表示,包含 \(N-2\) 个城市,每个城市都是顶点为 \(N\) 边形顶点的三角形,两人的旅游路线可以看做是连接N个顶点中不相邻两点的线段.问一路能经过 ...
- CF1416D Graph and Queries
本题解用于作者加深算法印象,也欢迎各位的阅读. 题目大意 给你一张无向图,并给你两种操作: \(1~v\) :找到当前点 \(v\) 所在的联通块内权值最大的点,输出该点权值并将其权值改为 \(0\) ...
- 计算机网络——HTTP知识点整理
1.HTTP简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议.它可以使浏览器更加高效,使网络传输减少.它 ...
- Jmeter之登录接口参数化实战
为了纪念我走过的坑(为什么有些简单的问题就是绊住我了,还是不够细啊) Jmeter之接口登录参数化实战 因为想要在登录时使用不同的数据进行测试,所以我选择了将数据进行参数化.因为涉及到新建一个接口的功 ...
- Kubernetes弃用Docker后怎么办?
本文转自Rancher Labs 近期,Kubernetes在其最新的Changelog中宣布,自Kubernetes 1.20之后将弃用Docker作为容器运行时.这一消息在云原生领域激起了不小的水 ...
- 大数据组件Kerberos安全访问关键代码
版本信息 <version.hbase>2.1.0-cdh6.2.1</version.hbase> <version.hadoop>3.0.0-cdh6.2.1& ...
- Hive JDBC执行load时无法从本地加载数据
通过hive-jdcv连接hive server,在应用服务端执行以下命令,报错:Hiver Server节点上找不到data.txt load data local inpath '/home/dw ...