python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌。python
logging的日誌分爲debug()、info()、warning()、error()、critical()五個級別
debug() 調試模式(詳細)
info() 記錄(無錯誤)
warning() 無錯誤但可能有潛在的危險
error() 出現錯誤
critical() 嚴重問題
基本用法 |
import logging # 基本使用:日誌打印 logging.warning("user [alex] attempted wrong password more than 3 times") logging.critical("server is down") """ WARNING:root:user [alex] attempted wrong password more than 3 times CRITICAL:root:server is down """
日誌寫入文件 |
import logging logging.basicConfig(filename='log_test.log', level=logging.INFO) logging.debug("This message should go to the log file") logging.info("so should this") logging.warning("And this,too") """ log_test.log中僅寫入了warning和info信息 """
在basicConfig中,filename指定了文件路徑,level=logging.INFO是把日誌記錄設置爲INFO,只輸入INFO或者比INFO級別更高的日誌(日誌級別過濾)。web
自定義日誌格式 |
import logging logging.basicConfig(filename='log_test.log', level=logging.DEBUG, format='%(asctime)s-%(name)s-%(filename)s-%(funcName)s-%(lineno)d-%(message)s', # 參數固定格式 datefmt='%m/%d/%Y %I:%M:%S %p') def sayhi(): logging.error("from sayhi....") sayhi() logging.debug("This message should go to the log file") logging.info("so should this") logging.warning("And this,too")
執行會生成log_test.log文件,文件內容以下:網絡
04/18/2018 03:19:00 PM-root-logging_module.py-sayhi-40-from sayhi.... 04/18/2018 03:19:00 PM-root-logging_module.py-<module>-42-This message should go to the log file 04/18/2018 03:19:00 PM-root-logging_module.py-<module>-43-so should this 04/18/2018 03:19:00 PM-root-logging_module.py-<module>-44-And this,too
除了能夠在日誌格式上加上時間以外,還能夠自定義不少格式:函數
參數格式介紹: %(levelno)s # 打印數字形式的日誌級別(10對應debug,20對應info,30對應warning) %(levelname)s # 打印文本形式的日誌級別 %(pathname)s # 調用日誌輸出函數的模塊的完整路徑名 %(filename)s # 調用日誌輸出函數的模塊的文件名 %(module)s # 調用日誌輸出函數的模塊名 %(funcName)s # 調用日誌輸出函數的函數名 %(lineNo)d # 調用日誌輸出函數的語句所在的代碼行(44) %(created)f # 當前時間,用UNIX標準的表示是時間(通常時間用datafmt便可) %(relaticeCreated)d # 輸出日誌信息時,自Logger建立以來的毫秒數 %(asctime)s # 字符串形式的當前時間,默認格式"2003-08-08 16:32:21,878",逗號後爲毫秒數 %(thread)d # 線程ID %(threadName)s # 線程名 %(process)d # 進程ID %(message)s # 用戶輸出的消息
日誌同時輸出到屏幕和文件 |
Python使用logging模塊記錄日誌涉及四個主要類:
一、logger提供了應用程序能夠直接使用的接口;
二、handler將(logger建立的)日誌記錄發送到合適的目的輸出;
三、filter對記錄的日誌過濾決定哪條日誌輸出;
四、formatter決定日誌記錄的最終輸出格式。工具
首先在輸出信息以前獲取一個logger對象,用getLogger()方法指定文件名;其次利用StreamHandler()輸送到屏幕,利用FileHandler('文件名')輸送到文件;再利用addHandler()方法將handler對象加進Logger對象中。接着能夠生成Formatter對象,設置文件輸出格式,利用setFormatter()方法將輸出格式綁定到hander對象上。測試
最後由Filters對象對日誌進行過濾,通常與Logger進行關聯,若是屏幕和文件的日誌過濾機制不一樣,能夠與handler進行關聯。ui
Logger組件 |
每一個程序在輸出信息以前都要得到一個Logger。Logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊、核心模塊能夠這樣得到它的Logger:this
LOG = logging.getLogger("chat.gui") # 圖形界面模塊 LOG2 = logging.getLogger("chat.kernal") # 核心模塊
指定日誌級別、綁定或刪除handler和filters:spa
# 指定最低的日誌級別,低於lel的級別將被忽略。debug是最低的內置級別,critical爲最高 logging.Logger.setLevel() # 低於指定級別將被忽略 # 添加或刪除指定的filter logging.Logger.addFilter() logging.Logger.removeFilter() # 添加或刪除指定的handler logging.Logger.addHandler() logging.Logger.removeHandler()
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能夠設置的日誌級別線程
handler模塊 |
handler對象負責發送相關信息到指定的目的地(控制檯、文件、網絡):
logging.Handler.setLevel() # 指定被處理信息級別 logging.Handler.setFormatter() # 給這個handler選擇一個格式 logging.Handler.addFilter() # 新增一個filter對象 logging.Handler.removeFilter() # 刪除一個filter對象
每一個Logger能夠附加多個Handler。接下來咱們就來介紹一些經常使用的Handler:
logging.handlers.RotatingFileHandler 同FileHandler相似,但能夠管理文件大小。當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立一個新的同名日誌文件繼續輸出。
# 好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲chat.log.1。不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息。它的函數是: RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]) """ 其中filename和mode兩個參數和FileHandler同樣。 maxBytes用於指定日誌文件的最大文件大小。若是maxBytes爲0,意味着日誌文件能夠無限大,這時上面描述的重命名過程就不會發生。 backupCount用於指定保留的備份文件的個數。好比,若是指定爲2,當上面描述的重命名過程發生時,原有的chat.log.2並不會被改名,而是被刪除。 """
logging.handlers.TimedRotatingFileHandler
這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。# 函數以下: TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]) """ 其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。 interval是時間間隔。 when參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值: S 秒 M 分 H 小時 D 天 W 每星期(interval==0時表明星期一) midnight 天天凌晨 """
formatter組件 |
日誌的formatter是個獨立的組件,能夠跟handler組合。
fh = logging.FileHandler("access.log") formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) #把formmater綁定到fh上
filter組件 |
對日誌過濾,可自定義一個filter,通用格式以下:(注意filter函數會返加True or False,logger根據此值決定是否輸出此日誌)
class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日誌""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage()
而後將這個filter添加到logger中:
logger.addFilter(IgnoreBackupLogFilter())
下面的日誌就會將符合filter條件的過濾掉
logger.debug("test ....") logger.info("test info ....") logger.warning("start to run db backup job ....") logger.error("test error ...."
同時輸出屏幕、文件、帶filter的例子 |
import logging class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日誌""" def filter(self, record): # 固定寫法 return "db backup" not in record.getMessage() # 字段不在日誌消息內 # 生成logger對象 logger = logging.getLogger("web") logger.setLevel(logging.DEBUG) # 不設置日誌級別,默認日誌級別是warning
# 把filter對象添加到logger中 logger.addFilter(IgnoreBackupLogFilter()) # 生成handler對象 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) # 屏幕debug級別 fh = logging.FileHandler("web.log") fh.setLevel(logging.WARNING) # 文件設置WARNING級別 # 把handler對象綁定到logger對象 logger.addHandler(ch) logger.addHandler(fh) # 生成formatter對象 file_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s') # 把formatter對象綁定hander對象 ch.setFormatter(console_formater) fh.setFormatter(file_formater) logger.debug("test_log") logger.warning("test_log_2") logger.debug("test log db backup 3") # filter測試,不記錄這條日誌 """ 在全局日誌級別:info (不設置默認級別是warning,通常能夠把全局設低把其餘級別設高) 屏幕日誌級別:debug 文件日誌級別:warning 這種狀況下,屏幕日誌級別不生效,依然按照全局日誌級別僅輸出一條: 2018-03-03 16:27:28,508 - web - WARNING - 23 - test_log_2 全局設置爲DEBUG後,console_handler設置爲INFO,若輸出的日誌級別爲DEBUG,則不會再屏幕顯示 """
能夠看到上述程序設置屏幕日誌級別爲debug, 文件日誌級別爲warning,同時過濾信息爲「db backup」。屏幕輸出和web.log文件日誌以下所示:
# 控制檯日誌 2018-04-18 16:34:21,376 - web - DEBUG - 32 - test_log 2018-04-18 16:34:21,376 - web - WARNING - 33 - test_log_2 # web.log日誌 2018-04-18 16:34:21,376 - web - WARNING - test_log_2
根據文件大小截斷日誌 |
函數示例:logging.RotatingFileHandler(filename[, mode[, maxBytes[, backupCount]]]),當文件達到必定大小後,會自動將當前日誌文件更名,而後建立一個新的同名的日誌文件繼續輸出。
import logging from logging import handlers class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日誌""" def filter(self, record): # 固定寫法 return "db backup" not in record.getMessage() # 字段不在日誌消息內 # 生成logger對象 logger = logging.getLogger("web") logger.setLevel(logging.DEBUG) # 不設置日誌級別,默認日誌級別是warning # 把filter對象添加到logger中 logger.addFilter(IgnoreBackupLogFilter()) # 生成handler對象 ch = logging.StreamHandler() # ch.setLevel(logging.DEBUG) # 屏幕debug級別 # 生成RotatingFileHandler對象 # fh = logging.FileHandler("web.log") fh = handlers.RotatingFileHandler("web_jd.log", maxBytes=10, backupCount=3) # 限制文件大小,日誌截斷 # fh.setLevel(logging.WARNING) # 文件設置WARNING級別 # 把handler對象綁定到logger對象 logger.addHandler(ch) logger.addHandler(fh) # 生成formatter對象 file_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s') # 把formatter對象綁定hander對象 ch.setFormatter(console_formater) fh.setFormatter(file_formater) logger.debug("test_log") logger.warning("test_log_2") logger.debug("test log db backup 3") """ 輸出web_jd.log.1 web_jd.log.2這三個文件 web_jd.log: 2018-03-03 16:54:32,307 - web - WARNING - test_log_2 web_jd.log.1: 2018-03-03 16:54:32,307 - web - DEBUG - test_log web_jd.log.2: 2018-03-03 16:53:38,900 - web - DEBUG - test_log 2018-03-03 16:53:38,901 - web - WARNING - test_log_2 """
根據時間截斷日誌 |
handlers.TimedRotatingFileHandler()方法
import logging from logging import handlers class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日誌""" def filter(self, record): # 固定寫法 return "db backup" not in record.getMessage() # 字段不在日誌消息內 # 生成logger對象 logger = logging.getLogger("web") logger.setLevel(logging.DEBUG) # 不設置日誌級別,默認日誌級別是warning # 把filter對象添加到logger中 logger.addFilter(IgnoreBackupLogFilter()) # 生成handler對象 ch = logging.StreamHandler() # ch.setLevel(logging.DEBUG) # 屏幕debug級別 # fh = logging.FileHandler("web.log") fh = handlers.TimedRotatingFileHandler("web_jd.log", when="S", interval=5, backupCount=3) # fh.setLevel(logging.WARNING) # 文件設置WARNING級別 # 把handler對象綁定到logger對象 logger.addHandler(ch) logger.addHandler(fh) # 生成formatter對象 file_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') console_formater = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s') # 把formatter對象綁定hander對象 ch.setFormatter(console_formater) fh.setFormatter(file_formater) logger.debug("test_log") logger.warning("test_log_2") logger.debug("test log db backup 3") """兩次執行生成兩個文件 文件web_jd.log.2018-04-18_19-29-22 2018-04-18 19:29:22,013 - web - WARNING - test_log_2 文件web_jd.log.2018-04-18_22-49-38 2018-04-18 22:49:38,467 - web - DEBUG - test_log 2018-04-18 22:49:38,469 - web - WARNING - test_log_2 """