python Logging日志记录模块详解

写在篇前

  logging是Python的一个标准库,其中定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统。Python logging 的配置由四个部分组成:Logger、Handlers、Filter、Formatter。本篇博客将依次介绍这四个主要部分以及logging的基本应用。

  在开始之前,我们有必要先了解一下,什么时候我们才有必要使用logging模块,什么时候抛出异常(raise Exception),什么时候使用简单的print函数即可,官方文档给我们总结了一个表格

Task you want to perform The best tool for the task
命令行终端输出或则程序一般的输出情景 print()
报告程序正常运行期间发生的事件(例如,状态监视或故障调查) logging.info()(或则 logging.debug() 用于诊断目的细节输出)
发出有关特定运行时事件的警告 warnings.warn() : 用于如果问题是可以避免的,且应修改应用程序以消除警告的情景;logging.warning()用于如果应用程序无法处理该情况,但仍应注意该事件的情景。
报告有关特定运行时事件的错误 Raise an exception
报告在不引发异常的情况下抑制错误(例如,长时间运行的服务器进程中的错误处理程序) logging.error(), logging.exception()或则logging.critical() 适用于特定错误和应用程序域

Loggers

  logger是暴露给代码进行日志操作的接口。需要注意的是,logger不应该直接实例化,而应通过模块级函数logging.getLogger(name)创建。如果name是具有层级结构的命名方式,则logger之间也会有层级关系。如name为foo.barfoo.bar.bazfoo.bam 的logger是foo的子孙,默认子logger日志会向父logger传播,可以通过logger.propagate=False禁止;对具有相同名称的getLogger()的多次调用将始终返回同一Logger对象的引用。logger对象的功能包括以下三项:

  1. 向应用程序暴露infodebug等方法,用于程序运行时进行日志记录;
  2. 根据log level(默认过滤工具)或Filter对象确定要处理的日志消息;
  3. 将日志消息传递给所有感兴趣的Log Handler;

  另外,需要理清以下两个概念:

  1. Log Record

    Each message that is written to the Logger is a Log Record. 可以使用makeLogRecord()函数创建record对象(一般用不上),record对象常用的属性如下,全部属性请参考官方文档

    • record.levelname # record level
    • record.levelno # record level number
    • record.msg # record承载的日志消息
    • record.pathname # emit该日志消息的程序文件
    • record.lineno # emit该日志消息的程序行号
    • record.getMessage() # 同record.msg

     从python 3.2起,logging模块提供了工厂函数getLogRecordFactory()setLogRecordFactory()方便、支持用户自定义record属性。

    old_factory = logging.getLogRecordFactory()
    
    def record_factory(*args, **kwargs):
        record = old_factory(*args, **kwargs)
        record.custom_attribute = 0xdecafbad
        return record
    
    logging.setLogRecordFactory(record_factory)
    
  2. Log Level

      每个logger都需要设置一个log level,该log level描述了logger将处理日志消息的级别; 每个log record也具有一个log Level,指示该特定日志消息的级别。 log record还可以包含被记录事件的metadata,包括诸如堆栈跟踪或错误代码之类的详细信息。如果设置了logger的log level,系统便只会输出 level 数值大于或等于该 level 的的日志结果,例如我们设置了输出日志 level 为 INFO,那么输出级别小于 INFO 的日志,如DEBUG 和 NOSET 级别的消息不会输出。logger还有一个effective level的概念,如果logger没有显式设置log level,则使用其parent logger的log level作为其effective level,其中root logger的默认log level是WARNING

    • NOTEST:lowest level

      # Level Num 0
       logger.setLevel(level=logging.NOTEST)
      
    • DEBUG: Low level system information for debugging purposes

       # Level Num 10
       logger.setLevel(level=logging.DEBUG
       logger.debug('Debugging')
      
    • INFO: General system information

      # Level Num 20
       logger.setLevel(level=logging.INFO)
       logger.info('This is a log info')
      
    • WARNING: Information describing a minor problem that has occurred.

      # Level Num 30,默认是该level
       logger.setLevel(level=logging.WARNING)
       logger.warning('Warning exists')
       logger.warn('Warning exists')  # deprecated
      
    • ERROR: Information describing a major problem that has occurred.

      # Level Num 40
       logger.setLevel(level=logging.ERROR)
       logger.error('some error occur')
      
    • CRITICAL: Information describing a critical problem that has occurred.

      # Level Num 50
       logger.setLevel(level=logging.NOTEST)
       
       logger.critical('critical err occur')
       logger.fatal('fatal error occur') 
      

  上面各个函数还有一个统一的调用方式logger.log(level, msg, exc_info=True),其中,level是指上面标注的level numexc_info指示是否打印执行信息;Logger.exception()创建与 Logger.error()相似的日志消息,不同之处是, Logger.exception()同时还记录当前的堆栈追踪,请仅从异常处理程序调用此方法。

  logger对象还有一些其他属性、方法值得关注:

>>>logger = logging.getLogger('main')  # 如果不指定name将会返回root logger
>>>logger.setLevel(level=logging.DEBUG)

>>>logger.disabled  # False
>>>logger.propagate=False
>>>logger.getEffectiveLevel()  # 10
>>>logger.isEnabledFor(20)  # True

>>>logging.disable(20)
>>>logger.isEnabledFor(20)  # False
>>>logger.isEnabledFor(30)  # True

>>>child_logger = logger.getChild('def.ghi')  # <Logger main.def.ghi (DEBUG)>


# Filter
addFilter(filter)
removeFilter(filter)

# handler
logger.hasHandlers()  # False
addHandler(hdlr)
removeHandler(hdlr)

  关于上面各种Level的调用情景,官方文档也给出了相应说明:

Level When it’s used
DEBUG Detailed information, typically of interest only when diagnosing problems.
INFO Confirmation that things are working as expected.
WARNING An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR Due to a more serious problem, the software has not been able to perform some function.
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值