标签:
logging模块主要可以根据自定义日志信息,在程序运行的时候将日志打印在终端及记录日志到文件中。在这先了解一下logging支持的日志五个级别
debug() 调试级别,一般用于记录程序运行的详细信息
info() 事件级别,一般用于记录程序的运行过程
warnning() 警告级别,,一般用于记录程序出现潜在错误的情形
error() 错误级别,一般用于记录程序出现错误,但不影响整体运行
critical 严重错误级别 , 出现该错误已经影响到整体运行
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#pyversion:python3.5
#owner:fuzj
import logging
logging.debug("User %s is loging" % 'jeck')
logging.info("User %s attempted wrong password" % 'fuzj')
logging.warning("user %s attempted wrong password more than 3 times" % 'mary')
logging.error("select db is timeout")
logging.critical("server is down")
输出结果:
WARNING:root:user mary attempted wrong password more than 3 times
ERROR:root:select db is timeout
CRITICAL:root:server is down
发现怎么没有debug和info的日志呢? 原来默认情况下,logging将日志打印到屏幕,日志级别为WARNING。而debug和info在warnning级别之下,所以不打印。我们可以调整一下终端输出级别,为美观一下,自定义日志格式
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#pyversion:python3.5
#owner:fuzj
import logging
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S')
logging.debug("User %s is loging" % 'jeck')
logging.info("User %s attempted wrong password" % 'fuzj')
logging.warning("user %s attempted wrong password more than 3 times" % 'mary')
logging.error("select db is timeout")
logging.critical("server is down")
输出结果
Thu, 09 Jun 2016 11:42:08 日志.py[line:13] DEBUG User jeck is loging
Thu, 09 Jun 2016 11:42:08 日志.py[line:14] INFO User fuzj attempted wrong password
Thu, 09 Jun 2016 11:42:08 日志.py[line:15] WARNING user mary attempted wrong password more than 3 times
Thu, 09 Jun 2016 11:42:08 日志.py[line:16] ERROR select db is timeout
Thu, 09 Jun 2016 11:42:08 日志.py[line:17] CRITICAL server is down
这样的输出结果看着还过得去。现在脑补一下上面用到的logging.basicConfig函数
logging.basicConfig
主要可以对日志的输出格式及方式做相关配置支持的参数由:
记录日志到文件
现在有了新需求,我不能只打印日志到终端呀,我想记录日志咋办?
很简单,使用上面的logging.basicConfig即可搞定
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#pyversion:python3.5
#owner:fuzj
import logging
#在logging.basciConfig中指定文件和写入方式
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S',filename="test.log",filemode='a')
logging.debug("User %s is loging" % 'jeck')
logging.info("User %s attempted wrong password" % 'fuzj')
logging.warning("user %s attempted wrong password more than 3 times" % 'mary')
logging.error("select db is timeout")
logging.critical("server is down")
输出效果:
此没有终端输出,发现在同级目录生成了一个test.log文件,打开看看,原来日志都已经写进去了,和上面终端输出的一样
Thu, 09 Jun 2016 11:57:41 日志.py[line:15] DEBUG User jeck is loging
Thu, 09 Jun 2016 11:57:41 日志.py[line:16] INFO User fuzj attempted wrong password
Thu, 09 Jun 2016 11:57:41 日志.py[line:17] WARNING user mary attempted wrong password more than 3 times
Thu, 09 Jun 2016 11:57:41 日志.py[line:18] ERROR select db is timeout
Thu, 09 Jun 2016 11:57:41 日志.py[line:19] CRITICAL server is down
同输出屏幕和记录日志
现在又有了新需求,我不能只把日志记录到文件,有些日志信息我还是想直接在屏幕输出,而且还不影响日志记录文件,此过程比较复杂,先准备点基础知识
下面看代码
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#pyversion:python3.5
#owner:fuzj
import logging
logger = logging.getLogger("test.conf") #创建一个logger,默认为root logger
logger.setLevel(logging.DEBUG) #设置全局log级别为debug。注意全局的优先级最高
hterm = logging.StreamHandler() #创建一个终端输出的handler,设置级别为error
hterm.setLevel(logging.ERROR)
hfile = logging.FileHandler("access.log") #创建一个文件记录日志的handler,设置级别为info
hfile.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #创建一个全局的日志格式
hterm.setFormatter(formatter) #将日志格式应用到终端handler
hfile.setFormatter(formatter) #将日志格式应用到文件handler
logger.addHandler(hterm) #将终端handler添加到logger
logger.addHandler(hfile) #将文件handler添加到logger
#定义日志msg,注意此时是logger,不是logging了
logger.debug("User %s is loging" % 'jeck')
logger.info("User %s attempted wrong password" % 'fuzj')
logger.warning("user %s attempted wrong password more than 3 times" % 'mary')
logger.error("select db is timeout")
logger.critical("server is down")
结果:
在终端输出:
2016-06-09 12:22:25,283 - test.conf - ERROR - select db is timeout
2016-06-09 12:22:25,283 - test.conf - CRITICAL - server is down
在日志文件里写入:
2016-06-09 12:22:25,283 - test.conf - INFO - User fuzj attempted wrong password
2016-06-09 12:22:25,283 - test.conf - WARNING - user mary attempted wrong password more than 3 times
2016-06-09 12:22:25,283 - test.conf - ERROR - select db is timeout
2016-06-09 12:22:25,283 - test.conf - CRITICAL - server is down
是不是很高大上?不要激动,这只是简单实现了而已。logging模块的功能远不止这些。下面将深入剖析logging的四大组件
先来干货,请看下面脚本:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#pyversion:python3.5
#owner:fuzj
import logging
#创建logger
logger = logging.getLogger() #创建默认logger
logger1 = logging.getLogger("testlog") #创建一个名为testlog1的logger实例logger1
logger2 = logging.getLogger("testlog") #创建一个名为testlog1的logger实例logger2
logger3 = logging.getLogger("testlog.child") #创建一个testlog子实例logger3
#设置logger的日志级别
logger1.setLevel(logging.DEBUG) #将logger1日志级别设置为debug
logger2.setLevel(logging.INFO) #将logger1日志级别设置为info
logger3.setLevel(logging.ERROR) #将logger1日志级别设置为warning
#创建handler
hterm = logging.StreamHandler() #输出到终端
hfile = logging.FileHandler("test.log") #输出到文件
#定义日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#将日志格式应用到handler
hterm.setFormatter(formatter)
hfile.setFormatter(formatter)
#给logger添加handler
logger.addHandler(hterm)
logger.addHandler(hfile)
logger1.addHandler(hterm)
logger1.addHandler(hfile)
logger2.addHandler(hterm)
logger2.addHandler(hfile)
logger3.addHandler(hterm)
logger3.addHandler(hfile)
#记录日志信息
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')
logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')
logger3.debug('logger3 debug message')
logger3.info('logger3 info message')
logger3.warning('logger3 warning message')
logger3.error('logger3 error message')
logger3.critical('logger3 critical message')
结果:文件和终端输出:
2016-06-09 14:55:46,136 - root - WARNING - logger warning message
2016-06-09 14:55:46,136 - root - ERROR - logger error message
2016-06-09 14:55:46,136 - root - CRITICAL - logger critical message
2016-06-09 14:55:46,136 - testlog - INFO - logger1 info message
2016-06-09 14:55:46,136 - testlog - INFO - logger1 info message
2016-06-09 14:55:46,137 - testlog - WARNING - logger1 warning message
2016-06-09 14:55:46,137 - testlog - WARNING - logger1 warning message
2016-06-09 14:55:46,137 - testlog - ERROR - logger1 error message
2016-06-09 14:55:46,137 - testlog - ERROR - logger1 error message
2016-06-09 14:55:46,137 - testlog - CRITICAL - logger1 critical message
2016-06-09 14:55:46,137 - testlog - CRITICAL - logger1 critical message
2016-06-09 14:55:46,137 - testlog - INFO - logger2 info message
2016-06-09 14:55:46,137 - testlog - INFO - logger2 info message
2016-06-09 14:55:46,137 - testlog - WARNING - logger2 warning message
2016-06-09 14:55:46,137 - testlog - WARNING - logger2 warning message
2016-06-09 14:55:46,137 - testlog - ERROR - logger2 error message
2016-06-09 14:55:46,137 - testlog - ERROR - logger2 error message
2016-06-09 14:55:46,137 - testlog - CRITICAL - logger2 critical message
2016-06-09 14:55:46,137 - testlog - CRITICAL - logger2 critical message
2016-06-09 14:55:46,137 - testlog.child - ERROR - logger3 error message
2016-06-09 14:55:46,137 - testlog.child - ERROR - logger3 error message
2016-06-09 14:55:46,137 - testlog.child - ERROR - logger3 error message
2016-06-09 14:55:46,137 - testlog.child - CRITICAL - logger3 critical message
2016-06-09 14:55:46,137 - testlog.child - CRITICAL - logger3 critical message
2016-06-09 14:55:46,137 - testlog.child - CRITICAL - logger3 critical message
logger一个树形层级结构,输出信息之前都要获得一个Logger,logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置.
从输出中发现,
1)root logger由于没有定义loglevel,所以默认是warning,所以输出三天记录
2)logger1 testlog.logger 定义的loglevel是debug,怎么输出的信息是虫info开始呢? 原来logger1和logger2对应的同一个logger实例,logger2重新定义了loglevel,所以logger1和logger2对应的实例loglevel级别就成了info,小心在这里出错
3)从日志条数上看,怎么logger1 和logger2重复输出了2次,logger2重复输出了三次呢,原来和logger的结构有关,他是树形结构,logger = logging.getLogger()显示的创建了root Logger,而我们继续创建的logger1 logger2 则是root logger实例的子实例,而logger3是logger1和logger2的子实例
logger2 = logging.getLogger("testlog")
logger3 = logging.getLogger("testlog.child")
看出来了吧,logger2对应的是testlog,而logger3对应的是testlog.child。这样可得知,一个logger不仅需要自己的handler处理消息,还会把消息发送给自己的父logger的handler。,而子logger如果没有定义日志级别、Handler、Filter等设置,会逐层继承父logger的设置,所以父logger会优先按子logger的属性进行处理,否则就按自己的处理,所以就出现了多次重复日志现象
handler
负责发送相关的信息到指定目的地
常用的Handler方法:
可用的handler类型有:
GET或
POST远程输出到HTTP服务器
具体参考:
https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers
filter
定义handler处理的规则
如定义一个规则
filter=logging.Filter('testlog.child') #符合testlog.child的才能记录日志到文件
hterm.addFilter(filter) #将filer应用到hterm的handle
执行结果:
终端输出:
2016-06-09 15:42:30,501 - testlog.child - ERROR - logger3 error message
2016-06-09 15:42:30,501 - testlog.child - ERROR - logger3 error message
2016-06-09 15:42:30,501 - testlog.child - ERROR - logger3 error message
2016-06-09 15:42:30,501 - testlog.child - CRITICAL - logger3 critical message
2016-06-09 15:42:30,501 - testlog.child - CRITICAL - logger3 critical message
2016-06-09 15:42:30,501 - testlog.child - CRITICAL - logger3 critical message
日志输出不变
此处是给logger加了filer,也可以给handler加,但是影响的酒不止一个logger了。他会影响所有使用这个handler的logger
用于定义输出的日志格式。用到的格式化内容可以参考logging.basicConfig()函数
#定义日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#将日志格式应用到handler
hterm.setFormatter(formatter)
hfile.setFormatter(formatter)
标签:
原文地址:http://www.cnblogs.com/pycode/p/logging.html