關於Python日誌系統的幾點建議

douxingxiang發表於2015-03-12

Python日誌系統非常豐富。新增結構化或非結構化日誌輸出到python程式碼,寫到檔案,輸出到控制檯,傳送到系統日誌,或者自定義輸出格式都很容易。

我們正在重新檢查mozharness中日誌的工作機制,希望提取程式碼能更容易,並減少摻合模式的使用。

下面是一些在python日誌中真正幫到我們的建議和技巧:

可以有多個logger

好吧,對一個給定名稱確實只會有一個logger。特殊的“根”logger沒有名稱。對相同名稱多次呼叫getLogger(name)會返回相同的logger物件。這個特性很重要,你不用在程式碼中顯式將logger物件傳來傳去。你可以通過名稱來獲取它們。日誌模組維護了一個全域性日誌物件登錄檔。

你可以使用多個logger物件,每個只限定於其特定模組,甚至類或例項。

每個logger都有一個名稱,通常是logger所處模組的名稱。你能在Python模組中看到的通用模式大概這樣:

這段程式碼沒錯是因為foo.py中,__name__等於”foo”。所以在此模組中,log物件只會用於這個模組。

logger可分級的

名稱空間中的logger名稱使用“.”來分層。這意味著如果你有foo.barfoo.baz兩個logger,你可以操作foo,這樣它的兩個子logger都會起作用。尤其是,你可以設定foo的日誌等級來顯示或忽略兩個子模組的除錯訊息。

日誌訊息類似事件,會在層次結構中流動

假設我們有個模組foo.bar:

當我們呼叫make_widget()時,程式碼生成了一個除錯日誌訊息。層次結構中的每個logger都有機會將這個訊息輸出、忽略、傳遞給父級。

日誌預設並沒有配置其等級(或設定為NOTSET))。這意味著logger只會把訊息傳遞給父級,然後不斷重複這個步驟,一直到根logger。

所以如果foo.barlogger沒有指定等級,訊息將繼續傳遞到foologger。如果foologger沒有指定等級,訊息將會傳遞給根logger。

這就是為什麼你通常需要在根logger上配置日誌輸出的原因;它通常會輸出全部訊息!!!這太常見了,所以有個專門的方法來配置根logger:logging.basicConfig()

這也允許我們根據訊息的來源使用混合等級的日誌輸出:

如果註釋掉setLevel(logging.DEBUG),你將不會看到任何訊息。

exc_info是最棒的

所有的內建日誌呼叫都支援exc_info關鍵字,如果它不是false,當前異常資訊將會附加到日誌訊息中,比如:

log.exception()是個特例,等價於log.error(..., exc_info=True)

Python 3.2引入了一個新的關鍵字stack_info,將會輸出當前棧到當前程式碼。當你想知道如何執行到程式碼的某處時,非常方便,即使沒有異常發生也可以。

“找不到處理函式…”

你很可能遇到過這個訊息,尤其是使用第三方模組時。這個錯誤的意思是,你沒有配置任何日誌處理函式,但是某處嘗試列印日誌訊息。這個訊息沿著層次結構向上傳遞,直到在結構鏈的頂處失敗(也許我需要一個更好的比喻)。

輸出:

這裡可以做兩件事:

1.在模組中使用basicConfig()或類似的方法配置日誌

2.庫作者應該在模組頂層新增一個NullHandler 來防止這種情況發生。看下這裡的指南這篇部落格來了解更多資訊。

更多?

我極力推薦你讀下日誌文件指南,它們提供了更多有用資訊(寫的也很好!)。你也可以通過定製自己的日誌處理器來做更多事情,不同的輸出格式、一次輸出到多個位置等。玩得高興!

相關文章