python logging模块的学习

logging模块

首先介绍logging模块中几个重要的角色:

一、对象介绍

  1. logger:主要提供日志接口,我们可以通过logging.getLogger(name)获得logger对象,如果不指定name,则返回root对象。
  2. handlers:将日志记录输出到制定的目的地,如文件,标准输出,socket。一个logger可以通过addHandlers添加handlers,每个handler可以自己定义日志的级别。比如,我们需要处理debug以上级别的消息,所以我们将logger的日志级别定为DEBUG;然后我们想把error以上的日志输出到控制台,而DEBUG以上的消息输出到文件中,file_hand.setLevel(logging.DEBUG),console.setLevel(logging.ERROR)
    handler主要有:StreamHandle()标准输出,FIleHandler,输出到标准文件;其他的在logging.handlers模块中:RotatingFileHandler(可以指定备份数目,以及文件最大容量),TimedRotatingFileHandler,SocketHandler,DatagramHandler,SMTPHandler,SysLogHandler,NTEventLogHandler,MemoryHandler,HTTPHandler,WatchedFileHandler
  3. formater:指定日志输出的具体格式。基本用法:%( )s的形式,就是字典的关键字替换。如:logging.Formatter( '%(asctime)s %(levelname)s %(message)s in %(filename)s %(levelno)s' )

当然这里要注意日志的级别,级别小于设定的将不会被输出,即若设置了ERROR级别,那么ERROR级别以下的将不会被输出。级别如下:


Level       Numeric value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

例子:


import logging

class MyLogger():

def __init__(self, name):
    self.logger = logging.getLogger(name)
    self._set_handlers()

def _set_handlers(self):
    self.logger.addHandler(self.sta_handler)
    self.logger.addHandler(self.file_handler)

@property
def sta_handler(self):
    formater = logging.Formatter(
        '%(asctime)s %(levelname)s %(message)s in %(filename)s %(levelno)s'
    )
    com_handler = logging.StreamHandler()
    com_handler.setLevel(logging.ERROR)
    com_handler.setFormatter(formater)
    return com_handler

@property
def file_handler(self):
    formater = logging.Formatter(
        '%(asctime)s %(levelname)s %(message)s in %(filename)s %(levelno)s'
    )
    com_handler = logging.FileHandler('s.log')
    com_handler.setLevel(logging.DEBUG)
    com_handler.setFormatter(formater)
    return com_handler

if name == "main": l = MyLogger('haibo').logger l.error('test error') l.warn('test warn')

在文件中,会输出:
2016-03-29 21:38:28,519 ERROR test error in my_log.py 40 2016-03-29 21:38:28,519 WARNING test warn in my_log.py 30
在标准输出只有: 2016-03-29 21:38:28,519 ERROR test error in my_log.py 40

二、模块继承

logger实例之间存在着父子关系,root logger是顶层的logger,它是所有logger的祖先。如果用getLogger获得对象时,如果不指定name,那么就是root。具体见下图:

1、level的继承
原则:子logger写日志时,优先使用本身设置了的level;如果没有设置,则逐层向上级父logger查询,直到查询到为止。最极端的情况是,使用rootLogger的默认日志级别logging.WARNING。
Python源码:


def getEffectiveLevel(self):
        """
        Get the effective level for this logger.

    Loop through this logger and its parents in the logger hierarchy,
    looking for a non-zero logging level. Return the first one found.
    """
    logger = self
    while logger:
        if logger.level:
            return logger.level
        logger = logger.parent
    return NOTSET

如果子对象没有添加handler等一些配置,会从父对象那继承。这样就可以通过这种继承关系来复用配置。
父子关系的表示形式如下:
logger的name的命名方式可以表示logger之间的父子关系. 比如:
parent_logger = logging.getLogger('foo')
child_logger = logging.getLogger('foo.bar')


sl = logging.getLogger('haibo.c')
sl.warn('test inherit')

输出:

2016-03-29 22:04:14,563 WARNING test inherit in my_log.py 30

这里面sl没有handler,就继承了l的handler。

三、日志配置

如果有多个handlers时,比较麻烦,我们可以将信息写到配置文件中。这个其实我感觉用的不多,暂时用不到logging配置。不过先记录下来,以备后续使用。


import logging
import logging.config
logging.config.fileConfig('logging.conf')

create logger

logger = logging.getLogger('simpleExample')

'application' code

logger.debug('debug message') logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message')

配置文件logging.conf的内容

[loggers] keys=root,simpleExample [handlers] keys=consoleHandler [formatters] keys=simpleFormatter [logger_root] level=DEBUG handlers=consoleHandler [logger_simpleExample] level=DEBUG handlers=consoleHandler qualname=simpleExample propagate=0 [handler_consoleHandler] class=StreamHandler level=DEBUG formatter=simpleFormatter args=(sys.stdout,) [formatter_simpleFormatter] format=%(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt=

--------EOF---------
微信分享/微信扫码阅读