Python 日誌記錄學習
日誌是一個系統的重要組成部分,用來記錄使用者操作、系統執行狀態和錯誤資訊,它的好壞直接影響到系統出現問題時定位的速度,有日誌記錄,我們可以在服務崩潰的時候很快的通過檢視日誌來發現問題出現的地方,同樣也可以通過對日誌的觀察和分析,提前發現系統可能存在的風險。
對於簡單地指令碼程式,出問題的時候只要使用 print 函式列印一下程式的中間結果即可,但也僅僅是對簡單的指令碼程式有效果。一旦碰到複雜的系統,如果還是隻用 print 這種方式的話,會看到大量的無用訊息,很難從中找到有用的內容。
Python 的標準日誌模組
Python 標準庫中提供了 logging 模組,最簡單的使用,預設情況下 logging 將日誌列印到螢幕終端,我們可以直接匯入 logging 模組,然後呼叫 debug,info,warn,error 和 critical 等函式來記錄日誌,預設日誌的重要性級別為 warning ,重要性級別比 warning 高的日誌才會被顯示(包括 warning ),重要性級別
重要性級別如下,DEBUG 到 CRITICAL 越來越高:
日誌等級(level) | 描述 |
---|---|
DEBUG | 最詳細的日誌資訊,典型應用場景是 問題診斷 |
INFO | 資訊詳細程度僅次於DEBUG,通常只記錄關鍵節點資訊,用於確認一切都是按照我們預期的那樣進行工作 |
WARNING | 當某些不期望的事情發生時記錄的資訊(如,磁碟可用空間較低),但是此時應用程式還是正常執行的 |
ERROR | 由於一個更嚴重的問題導致某些功能不能正常執行時記錄的資訊 |
CRITICAL | 當發生嚴重錯誤,導致應用程式不能繼續執行時記錄的資訊 |
logging模組的使用方式介紹
-
logging模組定義的模組級別的常用函式
函式 說明 logging.debug(msg, *args, **kwargs) 建立一條嚴重級別為DEBUG的日誌記錄 建立一條嚴重級別為INFO的日誌記錄 logging.warning(msg, *args, **kwargs) 建立一條嚴重級別為WARNING的日誌記錄 logging.error(msg, *args, **kwargs) 建立一條嚴重級別為ERROR的日誌記錄 logging.critical(msg, *args, **kwargs) 建立一條嚴重級別為CRITICAL的日誌記錄 logging.log(level, *args, **kwargs) 建立一條嚴重級別為level的日誌記錄 logging.basicConfig(**kwargs) 對root logger進行一次性配置 其中
logging.basicConfig(**kwargs)
函式用於指定“要記錄的日誌級別”、“日誌格式”、“日誌輸出位置”、“日誌檔案的開啟模式”等資訊,其他幾個都是用於記錄各個級別日誌的函式。 -
logging模組的四大元件
元件 說明 loggers 提供應用程式程式碼直接使用的介面 handlers 用於將日誌記錄傳送到指定的目的位置 filters 提供更細粒度的日誌過濾功能,用於決定哪些日誌記錄將會被輸出(其它的日誌記錄將會被忽略) formatters 用於控制日誌資訊的最終輸出格式 說明1: logging模組提供的模組級別的那些函式實際上也是通過這幾個元件的相關實現類來記錄日誌的,只是在建立這些類的例項時設定了一些預設值。
說明2:簡單點說就是:日誌器(logger)是入口,真正幹活兒的是處理器(handler),處理器(handler)還可以通過過濾器(filter)和格式器(formatter)對要輸出的日誌內容做過濾和格式化等處理操作。
使用logging提供的模組級別的函式記錄日誌
-
最簡單的日誌輸出
import logging logging.debug("This is a debug log.") logging.info("This is a info log.") logging.warning("This is a warning log.") logging.error("This is a error log.") logging.critical("This is a critical log.") # 也可以這樣寫 # logging.log(logging.DEBUG, "This is a debug log.") # logging.log(logging.INFO, "This is a info log.") # logging.log(logging.WARNING, "This is a warning log.") # logging.log(logging.ERROR, "This is a error log.") # logging.log(logging.CRITICAL, "This is a critical log.")
輸出結果為:
WARNING:root:This is a warning log. ERROR:root:This is a error log. CRITICAL:root:This is a critical log.
-
logging.basicConfig()函式說明
該方法用於為logging日誌系統做一些基本配置,方法定義如下:
logging.basicConfig(**kwargs)
該函式可接收的關鍵字引數如下:引數名稱 描述 filename 指定日誌輸出目標檔案的檔名,指定該設定項後日志信心就不會被輸出到控制檯了 filemode 指定日誌檔案的開啟模式,預設為’a’。需要注意的是,該選項要在filename指定時才有效 format 指定日誌格式字串,即指定日誌輸出時所包含的欄位資訊以及它們的順序。logging模組定義的格式欄位下面會列出。 datefmt 指定日期/時間格式。需要注意的是,該選項要在format中包含時間欄位%(asctime)s時才有效 level 指定日誌器的日誌級別 stream 指定日誌輸出目標stream,如sys.stdout、sys.stderr以及網路stream。需要說明的是,stream和filename不能同時提供,否則會引發 ValueError
異常style Python 3.2中新新增的配置項。指定format格式字串的風格,可取值為’%’、’{‘和’$’,預設為’%’ handlers Python 3.3中新新增的配置項。該選項如果被指定,它應該是一個建立了多個Handler的可迭代物件,這些handler將會被新增到root logger。需要說明的是:filename、stream和handlers這三個配置項只能有一個存在,不能同時出現2個或3個,否則會引發ValueError異常。 -
經過配置的日誌輸出
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p" logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT, datefmt=DATE_FORMAT) logging.debug("This is a debug log.") logging.info("This is a info log.") logging.warning("This is a warning log.") logging.error("This is a error log.") logging.critical("This is a critical log.")
在 my.log 中輸出的內容為:
12/07/2018 15:46:12 PM - DEBUG - This is a debug log. 12/07/2018 15:46:12 PM - INFO - This is a info log. 12/07/2018 15:46:12 PM - WARNING - This is a warning log. 12/07/2018 15:46:12 PM - ERROR - This is a error log. 12/07/2018 15:46:12 PM - CRITICAL - This is a critical log.
說明:logging.basicConfig()函式是一個一次性的簡單配置工具使,也就是說只有在第一次呼叫該函式時會起作用,後續再次呼叫該函式時完全不會產生任何操作的,多次呼叫的設定並不是累加操作。
logging日誌模組相關類及其常用方法介紹
-
Logger類
Logger物件有3個任務要做:
1)嚮應用程式程式碼暴露幾個方法,使應用程式可以在執行時記錄日誌訊息;
2)基於日誌嚴重等級(預設的過濾設施)或filter物件來決定要對哪些日誌進行後續處理;
3)將日誌訊息傳送給所有感興趣的日誌handlers。 -
Handler類
-
Formater類
-
Filter類
使用logging四大元件記錄日誌
import logging
import logging.handlers
import datetime
logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)
rf_handler = logging.handlers.TimedRotatingFileHandler('all.log', when='midnight', interval=1, backupCount=7, atTime=datetime.time(0, 0, 0, 0))
rf_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
f_handler = logging.FileHandler('error.log')
f_handler.setLevel(logging.ERROR)
f_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))
logger.addHandler(rf_handler)
logger.addHandler(f_handler)
logger.debug('debug message')
logger.info('info message')
logger.warning('warning message')
logger.error('error message')
logger.critical('critical message')
all.log檔案輸出:
2018-12-07 16:34:20,612 - DEBUG - debug message
2018-12-07 16:34:20,612 - INFO - info message
2018-12-07 16:34:20,612 - WARNING - warning message
2018-12-07 16:34:20,612 - ERROR - error message
2018-12-07 16:34:20,613 - CRITICAL - critical message
error.log檔案輸出:
2018-12-07 16:34:20,612 - ERROR - log.py[:81] - error message
2018-12-07 16:34:20,613 - CRITICAL - log.py[:82] - critical message
配置logging的三種方式
- 使用Python程式碼顯式的建立loggers, handlers和formatters並分別呼叫它們的配置函式;
- 建立一個日誌配置檔案,然後使用fileConfig()函式來讀取該檔案的內容;
- 建立一個包含配置資訊的dict,然後把它傳遞個dictConfig()函式;