核心概念
Python标准库自带日志模块logging,logging中涉及到4个核心组件,这些组件构建了logging体系。
- Logger: 应用程序直接使用的接口对象,通过logger操作完成表达日志输出要求.
- Handler: 交付由Logger创建的日志记录(logRecord)到其对应的目的地,比如控制台,文件,网络。
- Filter:对日志记录(logRecord)进行更细粒度过滤,控制是否应该输出对应的日志记录
- Formatter: 控制日志输出的格式
日志有重要性区分,对应不同的应用场景,logging模块中默认定义了5种重要性并且可扩展。
DEBUG < INFO < WARNING < ERROR < CRITICAL
默认的5种重要性和其它语言里的情况差不多,从左到右重要性依次升高。
每个Logger对象都由一个名字,惯例是每个模块都声明一个logger
logger = logging.getLogger(__name__)
Logger间通过名字构成层级关系,"x"名字的logger是"x.y"名字logger的父级logger,在层级的最顶层是一个叫做“root”的logger。对应五种默认的重要性,Logger有对应的方法,如:debug()
, info()
。
Logger与Handler都可以设置日志重要性级别,低于这个级别的日志记录将不会被输出。如果一个Logger没有重要性设置,则会以父级别Logger的重要性判断一个日志是否有效,如果父Logger也未设置,则会向爷爷辈找,直到“root”,默认重要级别为“WARNING”。
logger.setLevel(logging.DEBUG)
handler.setLevel(logging.DEBUG)
一个Logger可以指定多个Handler,和多个Filter,一个Handler也可以指定多个Filter,一个日志记录只用符合Logger本身的重要性级别和Filter要求,并且也符合Handler的重要性级别设定和其绑定的Filter要求,才会最终通过Handler绑定的Formatter格式化后被输出。
Logger在默认传播配置下会把自己的日志记录传播到父级别Logger处理,该行为可以配置关闭。
官方文档上有一张图,很好的说明了一个日志被输出的过程。
![在这里插入图片描述](https://img-blog.csdnimg.cn/49800377f0314ce68c710dd935f0dd06.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NreXVwd2FyZA==,size_16,color_FFFFFF,t_70#pic_center)
配置
logging模块早期有两种配置方式:
- 基于python代码的配置,直接调用
addHandler()
, setLevel()
等方法直接配置需要的log行为 - 基于文本配置文件,
fileConfig()
函数用户读取配置文件,在文本配置文件中定义及组合Logger, Handler等组件
后期加入了
- 基于字典配置
从而可以有更多灵活的方式保存配置信息,比如JSON,YAML等,在这些格式数据中定义及组合Logger, Handler等组件,只要最后能生成字典即可,dictConfig()
函数用户读取字典配置信息
性能调优
logging模块会在格式字符串必须计算的时候才会计算最终的日志消息,但是有时候消息参数本身的计算代价是高昂的,如果消息本身由于不符合日志重要性的设置不会被记录,那么将会导致无效的计算。
通过isEnabledFor()
方法可以避免消息参数无比要的计算
if logger.isEnabledFor(logging.DEBUG):
logger.debug('Message with %s, %s', expensive_func1(),
expensive_func2())
如果logger的层级较深,日志重要性且只在高层次的logger中被设置,isEnabledFor()
本身可能也存在性能问题,此时可以缓存方法的结果使用。
日志框架本身的异常
日志框架本身涉及为尽可能屏蔽自身发生的异常,避免导致应用不必要的停止。
除了SystemExit
和KeyboardInterupt
外, handleError()
方法将会传入handler的emit()
方法处理日志消息记录时产生的异常被调用,默认的实现是检查logging.raiseExceptions
,如果为True
,调用栈会被输出到sys.stderr
。
模块级方法
logging模块级别直接提供了对应5种重要性的的同名函数,这些函数最后会被代理到“root”logger的同名方法上,简单的日志输出需求下使用这些方法会很方便,默认设置的logger重要性为“WARNING”, 输出位置为“sys.stderr”。
import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything
basicConfig()
函数在任何日志打印函数调用前使用,可以快捷的对logging模块的行为,包括输出目标,输出的日志重要性等进行配置。
logging.basicConfig(filename='example.log',
encoding='utf-8',
format='%(asctime)s:%(levelname)s:%(message)s'
level=logging.DEBUG)
日志消息可以是格式字符串,也就是带有变量占位符的形式,在日志事件消息参数后传入对应变量即可,格式字符串的格式支持配置,默认为%-style
风格的格式字符串。
logging.warning('%s before you %s', 'Look', 'leap!')
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)