【博文推荐 】 python Howto之logging模块(1)
【博文推荐 】 python Howto之logging模块(1)
本博文出自Bkjia博客无名博主,有任何问题请进入博主页面互动讨论! 博文地址:http://xdzw608.blog.51cto.com/4812210/1608718 |
本文来源于对py2.7.9 docs中howto-logging部分加之源代码的理解。官方文档链接如下,我用的是下载的pdf版本,应该是一致的:https://docs.python.org/2/howto/logging.html
我们不按照文档上由浅入深的讲解顺序,因为就这么点东西不至于有“入”这个动作。
使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
写log的一般顺序为:
一、创建logger:
我们不要通过logging.Logger来直接实例化得到logger,而是需要通过logging.getLogger("name")来生成logger对象。
不 是说我们不能实现Logger的实例化,而是我们期待的是同一个name得到的是同一个logger,这样多模块之间可以共同使用同一个 logger,getLogger正是这样的解决方案,它内部使用loggerDict字典来维护,可以保证相同的名字作为key会得到同一个 logger对象。我们可以通过实例来验证一下:
- #test_logger1.py
- #coding:utf-8
- import logging
- print logging.getLogger("mydear")
- import test_logger2
- test_logger2.run() #调用文件2中的函数,保证两个模块共同处于生存期
- #test_logger2.py
- #coding:utf-8
- import logging
- def run():
- print logging.getLogger("mydear")
输出:
<logging.Logger object at 0x00000000020ECF28>
<logging.Logger object at 0x00000000020ECF28>
结果表明两个文件中通过"mydear"调用getLogger可以保证得到的logger对象是同一个。而分别进行Logger类的实例化则不能保证。
有了logger之后就可以配置这个logger,例如设置日志级别setLevel,绑定控制器addHandler,添加过滤器addFilter等。
配置完成后,就可以调用logger的方法写日志了,根据5个日志级别对应有5个日志记录方法,分别为logger.debug,logger.info,logger.warning,logger.error,logger.critical。
二、配置Logger对象的日志级别:
logger.setLevel(logging.DEBUG) #DEBUG以上的日志级别会被此logger处理
三、创建handler对象
handler 负责将log分发到某个目的输出,存在多种内置的Handler将log分发到不同的目的地,或是控制台,或是文件,或是某种形式的stream,或是 socket等。一个logger可以绑定多个handler,例如,一条日志可以同时输出到控制台和文件中。
以FileHandler和StreamHandler为例:
logfile= logging.FileHandler("./log.txt") #创建一个handler,用于将日志输出到文件中
console = logging.StreamHandler() #创建另一个handler,将日志导向流
handler对象也需要设置日志级别,由于一个logger可以包含多个handler,所以每个handler设置日志级别是有必要的。用通俗的话 讲,比如,我们需要处理debug以上级别的消息,所以我们将logger的日志级别定为DEBUG;然后我们想把error以上的日志输出到控制台,而 DEBUG以上的消息输出到文件中,这种分流就需要两个Handler来控制。
logfile.setLevel(logging.DEBUG)
console.setLevel(logging.ERROR)
除了对handler对象设置日志级别外,还可以指定formatter,即日志的输出格式。对handler对象设置日志格式,说明了可以将一条记录以不同的格式输出到控制台,文件或其他目的地。
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logfile.setFormatter(formatter) #设置handler的日志输出格式
formatter创建时使用的关键字,最后会以列表的形式展现,这不是重点。
四、绑定handler到logger中
至此handlers和logger已经准备好了,下面我们就将handlers绑定到logger上,一个logger对象可以绑定多个handler。
logger.addHandler(logfile) #logger是通过getLogger得到的Logger对象
logger.addHandler(console)
五、使用logger真正写日志
logger.debug("some debug message.")
logger.info("some info message.")
看上去,中间步骤(创建handler,设置日志级别,设置输出格式等)更像是配置Logger,一旦配置完成则直接调用写日志的接口即可,稍后这些日志将按照先前的配置输出。
呜呼,好多内容啊,来点简单的吧.
下面的代码,是最简单的。导入logging之后就进行了写日志操作:
- #coding:utf-8
- import logging
- logging.debug("debug mes")
- logging.info("info mes")
- logging.warning("warn mes")
控制台输出如下:
WARNING:root:warn mes
咦?发生了什么情况,为什么只输出了warning?handler、logger、formatter去哪儿了?
-_-!说好的最简单的呢?为了让自己讲信用,我尽可能把它解释成“最简单的”。
评论关闭