logging模塊能夠提供一個很簡單的basicConfig,可是它不夠強大,忘記它吧
html
使用logging模塊的loggerpython
import logging logger = logging.getLogger()#建立一個logger實例 # 建立一個handler實例,用於寫入日誌文件 logger.setLevel('DEBUG')#默認級別是WARNING fh = logging.FileHandler('test.log',encoding='utf-8') # 再建立一個handler實例,用於輸出到控制檯 ch = logging.StreamHandler() #建立格式實例 formatter = logging.Formatter('[%(asctime)s] %(levelname)s [%(pathname)s %(lineno)d [%(funcName)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S') fh.setLevel(logging.DEBUG)#若是logger的level級別比fh高,按logger的走 fh.setFormatter(formatter) #將第一個handler實例關聯格式實例 ch.setFormatter(formatter) #將第二個handler實例關聯格式實例 logger.addHandler(fh) #logger對象能夠添加多個fh和ch對象 logger.addHandler(ch) #試驗輸出 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')
先上一個簡單應用實例:服務器
logger記錄Exception
網絡
logger.exception("Exception Logged")
在介紹logging模塊的日誌流處理流程以前,咱們先來介紹下logging模塊的四大組件:函數
組件名稱 | 對應類名 | 功能描述 |
---|---|---|
日誌器 | Logger | 提供了應用程序可一直使用的接口 |
處理器 | Handler | 將logger建立的日誌記錄發送到合適的目的輸出 |
過濾器 | Filter | 提供了更細粒度的控制工具來決定輸出哪條日誌記錄,丟棄哪條日誌記錄 |
格式器 | Formatter | 決定日誌記錄的最終輸出格式 |
logging模塊就是經過這些組件來完成日誌處理的,上面所使用的logging模塊級別的函數也是經過這些組件對應的類來實現的。工具
簡單點說就是:日誌器(logger)是入口,真正幹活兒的是處理器(handler),處理器(handler)還能夠經過過濾器(filter)和格式器(formatter)對要輸出的日誌內容作過濾和格式化等處理操做。post
下面介紹下與logging四大組件相關的類:Logger, Handler, Filter, Formatter。url
Logger對象有3個任務要作:spa
Logger對象最經常使用的方法分爲兩類:配置方法 和 消息發送方法debug
最經常使用的配置方法以下:
方法 | 描述 |
---|---|
Logger.setLevel() | 設置日誌器將會處理的日誌消息的最低嚴重級別 |
Logger.addHandler() 和 Logger.removeHandler() | 爲該logger對象添加 和 移除一個handler對象 |
Logger.addFilter() 和 Logger.removeFilter() | 爲該logger對象添加 和 移除一個filter對象 |
關於Logger.setLevel()方法的說明:
內建等級中,級別最低的是DEBUG,級別最高的是CRITICAL。例如setLevel(logging.INFO),此時函數參數爲INFO,那麼該logger將只會處理INFO、WARNING、ERROR和CRITICAL級別的日誌,而DEBUG級別的消息將會被忽略/丟棄。
logger對象配置完成後,可使用下面的方法來建立日誌記錄:
方法 | 描述 |
---|---|
Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), Logger.critical() | 建立一個與它們的方法名對應等級的日誌記錄 |
Logger.exception() | 建立一個相似於Logger.error()的日誌消息 |
Logger.log() | 須要獲取一個明確的日誌level參數來建立一個日誌記錄 |
說明:
- Logger.exception()與Logger.error()的區別在於:Logger.exception()將會輸出堆棧追蹤信息,另外一般只是在一個exception handler中調用該方法。
- Logger.log()與Logger.debug()、Logger.info()等方法相比,雖然須要多傳一個level參數,顯得不是那麼方便,可是當須要記錄自定義level的日誌時仍是須要該方法來完成。
那麼,怎樣獲得一個Logger對象呢?一種方式是經過Logger類的實例化方法建立一個Logger類的實例,可是咱們一般都是用第二種方式--logging.getLogger()方法。
logging.getLogger()方法有一個可選參數name,該參數表示將要返回的日誌器的名稱標識,若是不提供該參數,則其值爲'root'。若以相同的name參數值屢次調用getLogger()方法,將會返回指向同一個logger對象的引用。
關於logger的層級結構與有效等級的說明:
- logger的名稱是一個以'.'分割的層級結構,每一個'.'後面的logger都是'.'前面的logger的children,例如,有一個名稱爲 foo 的logger,其它名稱分別爲 foo.bar, foo.bar.baz 和 foo.bam都是 foo 的後代。
- logger有一個"有效等級(effective level)"的概念。若是一個logger上沒有被明確設置一個level,那麼該logger就是使用它parent的level;若是它的parent也沒有明確設置level則繼續向上查找parent的parent的有效level,依次類推,直到找到個一個明確設置了level的祖先爲止。須要說明的是,root logger老是會有一個明確的level設置(默認爲 WARNING)。當決定是否去處理一個已發生的事件時,logger的有效等級將會被用來決定是否將該事件傳遞給該logger的handlers進行處理。
- child loggers在完成對日誌消息的處理後,默認會將日誌消息傳遞給與它們的祖先loggers相關的handlers。所以,咱們沒必要爲一個應用程序中所使用的全部loggers定義和配置handlers,只須要爲一個頂層的logger配置handlers,而後按照須要建立child loggers就可足夠了。咱們也能夠經過將一個logger的propagate屬性設置爲False來關閉這種傳遞機制。
Handler對象的做用是(基於日誌消息的level)將消息分發到handler指定的位置(文件、網絡、郵件等)。Logger對象能夠經過addHandler()方法爲本身添加0個或者更多個handler對象。好比,一個應用程序可能想要實現如下幾個日誌需求:
一個handler中只有很是少數的方法是須要應用開發人員去關心的。對於使用內建handler對象的應用開發人員來講,彷佛惟一相關的handler方法就是下面這幾個配置方法:
方法 | 描述 |
---|---|
Handler.setLevel() | 設置handler將會處理的日誌消息的最低嚴重級別 |
Handler.setFormatter() | 爲handler設置一個格式器對象 |
Handler.addFilter() 和 Handler.removeFilter() | 爲handler添加 和 刪除一個過濾器對象 |
須要說明的是,應用程序代碼不該該直接實例化和使用Handler實例。由於Handler是一個基類,它只定義了素有handlers都應該有的接口,同時提供了一些子類能夠直接使用或覆蓋的默認行爲。下面是一些經常使用的Handler:
Handler | 描述 |
---|---|
logging.StreamHandler | 將日誌消息發送到輸出到Stream,如std.out, std.err或任何file-like對象。 |
logging.FileHandler | 將日誌消息發送到磁盤文件,默認狀況下文件大小會無限增加 |
logging.handlers.RotatingFileHandler | 將日誌消息發送到磁盤文件,並支持日誌文件按大小切割 |
logging.hanlders.TimedRotatingFileHandler | 將日誌消息發送到磁盤文件,並支持日誌文件按時間切割 |
logging.handlers.HTTPHandler | 將日誌消息以GET或POST的方式發送給一個HTTP服務器 |
logging.handlers.SMTPHandler | 將日誌消息發送給一個指定的email地址 |
logging.NullHandler | 該Handler實例會忽略error messages,一般被想使用logging的library開發者使用來避免'No handlers could be found for logger XXX'信息的出現。 |
Formater對象用於配置日誌信息的最終順序、結構和內容。與logging.Handler基類不一樣的是,應用代碼能夠直接實例化Formatter類。另外,若是你的應用程序須要一些特殊的處理行爲,也能夠實現一個Formatter的子類來完成。
Formatter類的構造方法定義以下:
logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
可見,該構造方法接收3個可選參數:
Filter能夠被Handler和Logger用來作比level更細粒度的、更復雜的過濾功能。Filter是一個過濾器基類,它只容許某個logger層級下的日誌事件經過過濾。該類定義以下:
class logging.Filter(name='') filter(record)
好比,一個filter實例化時傳遞的name參數值爲'A.B',那麼該filter實例將只容許名稱爲相似以下規則的loggers產生的日誌記錄經過過濾:'A.B','A.B,C','A.B.C.D','A.B.D',而名稱爲'A.BB', 'B.A.B'的loggers產生的日誌則會被過濾掉。若是name的值爲空字符串,則容許全部的日誌事件經過過濾。
filter方法用於具體控制傳遞的record記錄是否能經過過濾,若是該方法返回值爲0表示不能經過過濾,返回值爲非0表示能夠經過過濾。
說明:
- 若是有須要,也能夠在filter(record)方法內部改變該record,好比添加、刪除或修改一些屬性。
- 咱們還能夠經過filter作一些統計工做,好比能夠計算下被一個特殊的logger或handler所處理的record數量等。