日志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信息时,就无法打印出来,只能打印INFOWARNINGERRORCRITICAL的日志。如果要打印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运行后,文件的记录内容: