python logging模块的学习
logging模块
首先介绍logging模块中几个重要的角色:
一、对象介绍
- logger:主要提供日志接口,我们可以通过logging.getLogger(name)获得logger对象,如果不指定name,则返回root对象。
-
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 -
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=
微信分享/微信扫码阅读
