日志logging模块
日志记录的作用:基本上就是收集与程序运行有关的数据,这样可以在随后进行检查(或者累计数据)
logging.basicConfig函数的配置:
filename:指定日志文件名
filemode:指定日志文件的打开模式,‘w’或‘a’
format:指定输出格式和内容,format可以输出很多有信息。
%(levelno)s:打印日志级别的数值
%(levelname)s:打印日志级别名称
%(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s:打印当前执行程序名
%(funcName)s:打印日志的当前函数
%(lineno)s:打印日志的当前行号
%(asctime)s:打印日志的时间
%(thread)s:打印线程ID
%(threadName)s:打印线程名称
%(process)s:打印进程ID
%(message)s:打印日志信息
datefmt:指定时间格式,同time.strftime()
level:设置日志级别,默认为logging.WARNING
stream:指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略。
selLevel()方法的级别
level numeric value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
logging包默认给出6个级别,最高级为CRITICAL,最低级为NOTSET。高级别的日志会覆盖低级别的日志信息,比如,如果定义setLevel(INFO),那么打印debug信息时,就无法打印出来,只能打印INFO\WARNING\ERROR\CRITICAL的日志。如果要打印debug的信息,则可以设置setLevel为:DEBUG或NOTSET。
创建日志实例:import logging
import time
# 获取logger实例,如果参数为空则返回root logger
logger = logging.getLogger()
# 指定logger输出格式
formatter=logging.Formatter("[%(levelname)s]--%(asctime)s-%(filename)s->%(funcName)s line:%(lineno)d: %(message)s")
# 文件日志
file_handler = logging.FileHandler("test.log",'a')
file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式
# 控制台日志
console_handler = logging.StreamHandler()
console_handler.formatter = formatter # 也可以直接给formatter赋值
# 为logger添加的日志处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 指定日志的最低输出级别,默认为WARNING级别
logger.setLevel(logging.INFO)
#日志打印参数
parameter1="20"
parameter2="30"
# 输出不同级别的log
logger.debug('this is debug info , parameter1=%s - parameter2=%s' %(parameter1,parameter2))
logger.info('this is information , parameter1=%s - parameter2=%s' %(parameter1,parameter2))
logger.warn('this is warning message , parameter1=%s - parameter2=%s' %(parameter1,parameter2))
logger.error('this is error message , parameter1=%s - parameter2=%s' %(parameter1,parameter2))
logger.fatal('this is fatal message, it is same as logger.critical , parameter1=%s - parameter2=%s' %(parameter1,parameter2))
logger.critical('this is critical message , parameter1=%s - parameter2=%s' %(parameter1,parameter2))
# 移除一些日志处理器
logger.removeHandler(file_handler)
logger.removeHandler(console_handler)
运行结果:
[INFO]--2018-12-23 10:43:28,453-test.py-><module> line:34: this is information , parameter1=20 - parameter2=30
[WARNING]--2018-12-23 10:43:28,453-test.py-><module> line:35: this is warning message , parameter1=20 - parameter2=30
[ERROR]--2018-12-23 10:43:28,453-test.py-><module> line:36: this is error message , parameter1=20 - parameter2=30
[CRITICAL]--2018-12-23 10:43:28,453-test.py-><module> line:37: this is fatal message, it is same as logger.critical , parameter1=20 - parameter2=30
[CRITICAL]--2018-12-23 10:43:28,453-test.py-><module> line:38: this is critical message , parameter1=20 - parameter2=30
[Finished in 0.1s]
重新封装logging(此处参考网上的代码进行修改)
#-*-encoding:utf-8-*-
import logging
import time
class TestLog(object):
#封装logging
def __init__(self,logger=None):
self.logger=logging.getLogger(logger)
self.logger.setLevel(logging.NOTSET)
self.log_time=time.strftime("%Y_%m_%d_")
self.log_path="D:\\"
self.log_name=self.log_path+self.log_time+"test.log"
def set_logger(self):
if not self.logger.handlers: #判断如果handlers中无handler则添加新的handler
self.fh=logging.FileHandler(self.log_name,"a") #创建将日志写入到文件,a表示以追加的形式写入日志
self.fh.setLevel(logging.DEBUG)
self.chd=logging.StreamHandler() #创建从控制台输入日志
self.chd.setLevel(logging.DEBUG) #设置为notset,可以打印debug、info、warning、error、critical的日志级别
self.formatter=logging.Formatter("[%(levelname)s]--%(asctime)s-%(filename)s->%(funcName)s line:%(lineno)d: %(message)s")
self.chd.setFormatter(self.formatter)
self.logger.addHandler(self.fh) #添加文件日志的日志处理器
self.logger.addHandler(self.chd) #添加控制台的日志处理器
def get_logger(self):
TestLog.set_logger(self)
# print self.logger.handlers 打印handlers列表
return self.logger
def remove_log_handler(self):
#移除handlers中的元素
self.logger.removeHandler(self.fh) #移除句柄,避免重复打印相同的日志
self.logger.removeHandler(self.chd) #移除句柄,避免重复打印相同的日志
self.fh.close() #关闭日志处理器
self.chd.close() #关闭日志处理器
if __name__=="__main__":
#调式是否能打印成功
test=TestLog()
log=test.get_logger()
log.warning("this is warning information")
log.info("this is info informattion")
log.info("this is info informattion1")
log.debug("this is debug information")
运行结果:
[WARNING]--2018-12-23 10:21:04,698-TestLog.py-><module> line:52: this is warning information
[INFO]--2018-12-23 10:21:04,698-TestLog.py-><module> line:53: this is info informattion
[INFO]--2018-12-23 10:21:04,698-TestLog.py-><module> line:54: this is info informattion1
[DEBUG]--2018-12-23 10:21:04,698-TestLog.py-><module> line:55: this is debug information
[Finished in 0.2s]
创建测试脚本,调用已封装好的TestLog类
#-*-encoding:utf-8-*-
import TestLog
import unittest
class MyTest(unittest.TestCase):
#测试日志是否能正常记录信息
def setUp(self):
self.a=10
self.b=12
self.log=TestLog.TestLog().get_logger()
def test1(self):
result=self.a+self.b
value=23
try:
self.assertEqual(result,value)
self.log.debug("parament1:%s - parament2:%s :puls=%s <-> value=%s" %(self.a,self.b,result,value))
except Exception as e:
self.log.error("异常原因:%s" %e)
def test2(self):
try:
a=0
b=10
result=b/a
self.log.debug("parament1:%s - parament2:%s " %(a,b,result))
except Exception as e:
self.log.error("异常原因:%s" %e)
def test3(self):
try:
a=u"测试"
b=u"测试"
self.assertEqual(a,b)
self.log.info("parament1:%s - parament2:%s " %(a,b))
except Exception as e:
self.log.error("异常原因:%s" %e)
def test4(self):
try:
a=u"测试a"
b=u"测试a"
self.assertEqual(a,b)
self.log.info("parament1:%s - parament2:%s " %(a,b))
except Exception as e:
self.log.error("异常原因:%s" %e)
def tearDonw(self):
pass
if __name__=="__main__":
unittest.main()
运行结果:
[ERROR]--2018-12-23 10:26:50,785-MyTest.py->test1 line:24: 异常原因:22 != 23
.[ERROR]--2018-12-23 10:26:50,785-MyTest.py->test2 line:34: 异常原因:integer division or modulo by zero
.[INFO]--2018-12-23 10:26:50,785-MyTest.py->test3 line:43: parament1:测试 - parament2:测试
.[INFO]--2018-12-23 10:26:50,785-MyTest.py->test4 line:53: parament1:测试a - parament2:测试a
MyTest运行后,文件的记录内容: