python logging日誌記錄
日誌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執行後,檔案的記錄內容: