僅僅將棧信息輸出到控制臺是遠遠不夠的,更為常見的是使用日誌保存程序運行過程中的相關信息,如運行時間、描述信息以及錯誤或者異常發生時候的特定上下文信息。
Python中自帶的logging模塊提供了日誌功能,它將logger的level分為5個級別,可以通過Logger.setLevel(lvl)來設置,其中DEBUG為最低級別,CRITICAL為最高級別. 默認的級別為WARNING。
logging lib包含以下4個主要對象:
(1) logger
logger是程序信息輸出的接口,它分散在不同的代碼中使得程序可以在運行的時候記錄相應的信息.並根據設置的日誌級別或filter來決定哪些信息需要輸出,並將這些信息分發到其關聯的handler。
常用的方法有Logger.setLevel()、 Logger.addHandler()、Logger.removeHandler()、Logger.addFilter()、Logger.debug()、 Logger.info()、Logger.warning()、Logger.error()、 etLogger()等。
(2)Handler
Handler用來處理信息的輸出,可以將信息輸出到控制臺、文件或者網絡。可以通過 Logger.addHandler()來給logger對象添加 handler,常用的handler有StreamHandler和FileHandler類。StreamHandler發送錯誤信息到流,而FileHandler類用於向文件輸出日誌信息,這兩個handler定義在logging的核心模塊中c其他的handler定義在logging.handles 模塊中,如 HTTPHandler、SocketHandler。
(3) Formatter
決定log信息的格式,格式使用類似於%(<dictionary key>)s的形式來定義,如'%(asctime)s - %(levelname)s - %(message)s'支持的key可以在Python自帶的文檔 LogRecord attributes 中査看
(4) Filter
用來決定哪些信息需要輸出。可以被handler和logger使用,支持層次關係,比如,如果設置了 filter名稱為A.B的logger,則該logger和其子logger的信息會被輸出, 如 A.B.、A.B.C.
logging.basicConfig([**kwargs])提供對日誌系統的基本配置,默認使用StreamHandler和Fonnatter並添加到root logger,字典參數如下所示。
我們通過修改上面的例子來看如何結合traceback和logging,記錄程序運行過程中的異常。
修改程序後在控制臺上對用戶僅顯示錯誤提示信息"Sorry,Exception occured,you accessed an element out of range",而開發人員如果需要debug可以在日誌文件中找到具體運行過程中的信息。
上面的代碼中控制運行輸岀到console上用的是print(),但這種方法比較原始,logging模塊提供了能夠同時控制輸出到console和文件的方法。
下面的例子中通過添加StreamHandler並設置日誌級別為logging.ERROR,可以在控制臺上輸出錯誤信息。
為了使Logging使用更為簡單可控,logging支持loggin.config進行配置,支持dictConfig和fileConfig兩種形式,其中fileConfig是基於configparser()函數進行解析,必須包含的內容為[loggers]、[handlers]和[formatters]。具體例子示意如下:
最後關於logging的使用,提以下幾點建議:
(1)儘量為logging取一個名字而不是採用默認,這樣當在不同的模塊中使用的時候,其他模塊只需要使用以下代碼就可以方便地使用同一個logger.因為它本質上符合單例模式。
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
(2)為了方便地找出問題所在,logging的名字建議以模塊或者class來命名。
Logging名稱遵循按"."劃分的繼承規則,根是root logger, logger a.b的父logger對象為a。
(3)Logging R是線程安全的,不支持多進程寫入同一個日子文件,因此對於多個進程,需要配置不同的日誌文件。