Python logging 的巧妙設計

2021-09-28 18:46:29 字數 2225 閱讀 6046

引言

logging 的基本用法網上很多,這裡就不介紹了。在引入正文之前,先來看乙個需求:

假設需要將某功能封裝成類庫供他人使用,如何處理類庫中的日誌?

數年前在乙個 c# 開發的專案中,我用了這樣的方法:定義乙個 logging 基類,所有需要用到日誌的類都繼承這個基類,這個基類中定義乙個 loghandler 事件,該事件用於實現具體的記錄日誌動作,同時可以通過將類 a 的 loghandler 委託掛到類 b 的 loghandler 上,實現將兩個類的日誌資訊新增到一起。

自從看了 python 中 logging 的實現方式,我發現我的做法真是弱爆了。

我在之前的部落格 python:logging.nullhandler 的使用 中介紹了 peewee 框架中的日誌輸出,簡單來說就是 peewee 中定義了乙個名為peewee 的 logger 並新增了乙個 nullhandler,呼叫者只需要為其新增具體的 handler 就可以輸出日誌了,非常方便。

假設我們在主程式中也有乙個 logger,呼叫 peewee 後,我想將兩個日誌輸出到同乙個日誌檔案中去。顯然將兩個日誌的 filehandler 指向同乙個日誌檔案是不可取的,存在併發搶占檔案的風險。當然我們也可以將主程式中的 logger 名字定為 peewee,但這不僅太 low 了,而且如果再呼叫乙個庫,其中也封裝好了乙個 logger,就不好處理了。

樹樁結構的 logger

logger 物件被設計為乙個樹形結構,它有乙個 parent 屬性。logging 中定義了乙個名為 root 的 logger 作為所有 logger 的根節點,root 的 parent 屬性為 none。root 是全域性的。

當呼叫

logging.getlogger(name=

none

)

得到乙個 logger 物件的時候,如果 name 為 none,則返回根節點 root。如果 name 中含有 .,比如 name = 『a.b』,這時如果已經存在了名為 a 的 logger,則 a.b 為 a 的子節點,如果不存在名為 a 的 logger,則 a.b 為 root 的子節點。

child logger 在完成對日誌訊息的處理後,缺省會將日誌訊息傳遞給與它的 parent logger。因此,我們不必為乙個應用程式中使用的所有 logger 定義和配置 handlers,只需要為乙個頂層的 logger 配置 handlers,然後按照需要建立 child loggers 就可足夠了。我們可以通過設定 logger 的 propagate 屬性設定為 false 來關閉這種傳遞機制。

什麼意思呢,我們來看**:

'''

'''import logging

loga = logging.getlogger(

'a')

loga.setlevel(logging.debug)

loga.addhandler(logging.streamhandler())

logb = logging.getlogger(

'a.b'

)logb.addhandler(logging.streamhandler())

輸出結果:

logger a

logger b

logger b

之所以 logger b 被輸出了 2 次,是因為 logb 是 loga 的子節點,並且 logb 中也定義了 handler,所以 logb 的 handler 輸出了一次,loga 的 handler 也輸出了一次,就 2 次了。如果想只輸出一次,可以刪掉 logb 中的 handler。當然,這也是有用處的,尤其是當你手頭沒有日誌管理工具的時候。例如,主程式中需要輸出所有的日誌,以便了解程式整體的執行順序,而某模組的日誌,你想單獨輸出乙份,以便清晰了解模組中的報錯或者是執行順序。

之前 peewee 的例子也就很容易解決了,只需要將 peewee 日誌的 parent 屬性設定為主程式的日誌就可以了。

結語

其實這是乙個比較容易說明的問題,完全沒必要寫這麼多。我並不想跟大家分享 python 中的 logging 是怎麼用的,而是想和大家分享 logging 如此實現的一種思想,因為我遇到過這個問題,也設計了解決方案,然後被完爆了。

python logging 最佳實踐

建立乙個logger,這裡的級別debug是總開關,控制了下面file 和console handler的級別 logger logging.getlogger logger.setlevel logging.debug 建立乙個handler,用於寫入日誌檔案,並定義輸出格式 fh logging...

Python logging模組學習

import logging 日誌級別列表,預設為logging.warning levels logging.notset,logging.debug,logging.info,logging.warning,logging.error,logging.critical log format as...

python logging模組簡介

logging模組是python內建的標準模組,主要用於輸出執行日誌,可以設定輸出日誌的等級 日誌儲存路徑 日誌檔案回滾等。相對於print,該模組具有可以決定在列印什麼級別的資訊和將資訊輸出放置在什麼地方的優點。配置logging的基本設定,並在控制台輸出 import logging loggi...