引言
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 如此實現的一種思想,因為我遇到過這個問題,也設計了解決方案,然后被完爆了。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
