python程式設計之logging模組的使用

2021-09-29 09:58:09 字數 4247 閱讀 9876

程式設計中,很多時候我們需要儲存乙個程式的中間輸出,要了解乙個程式的運**況,記錄程式執行中在一些關鍵節點處的資訊,以便我們後續進行分析和問題的排查。對於簡單的應用和相對不那麼複雜的程式,我們當然可以通過最常用的print來實現這些需求,無論是輸出到控制台還是重定向到磁碟檔案。但是一旦程式的功能性和複雜性提公升了,我們一直使用print會顯得雜亂,而且print的意義有時候也不明顯,print一般只適合對於區域性問題的排查,對於較多的資訊記錄,print就顯得有些無力,因為我們要讓記錄資訊顯得規範而且意義明確,用print會比較繁瑣,而且也不高效。對此,python有乙個標準庫logging,就是專門用以滿足這種需求的,其可以讓結果輸出更加的規範,意義更加明確,而且也可以對不同的資訊進行管理,相當於是乙個日誌管理工具。本文將基於官方文件,總結一下loggin的用法,分為基礎用法和高階用法兩部分。

直接匯入logging後,利用logging的函式來列印或者儲存資訊,基本的函式有:debug(),info(),warning(),error(),critical(),其等級依次遞增。所謂等級level的概念是用以表示一條訊息的嚴重等級,比如debug是最低等級,info次之,表示其對應的訊息對於程式來說不那麼嚴重,只是為了記錄程式的運**況,或者用以問題排查,而後面的warning則一般表示警告,表示程式出現了需要注意的結果,可能會對後續執行造成影響,以此類推。當然,這些函式名只是為了區分不同的使用場景,以讓使用者更好的識別資訊,如果硬是要對debug對應的場景用critical函式輸出或儲存訊息,也是可以的,訊息也可以輸出和儲存,只是意義變得混淆而已,不影響使用。

logging中一共有5個level,對應不同的使用場景,具體的可以看下圖。

如下所示,當執行如下語句時,會在控制台輸出如下內容。

import logging

logging.info('info test')

logging.warning('warning test')

logging.critical('critical test')

# output:

# warning:root:warning test

# critical:root:critical test

輸出的內容中,預設是以(level name):(logger name):(message)的格式,其中關於logger name,後面的高階用法部分會講到。從輸出的結果可以看到,logging.info語句的內容並沒有輸出,只輸出了warning和critical的內容,原因是logging預設只輸出level等於以及高於warging的資訊,所以level為info的便不會輸出;當然,我們可以通過設定level改變這個行為,如下所示,同時logging輸出的地方預設是控制台,當然也可以通過如下方式,即利用logging的basicconfig函式進行設定,將輸出的內容儲存在乙個檔案中。

import logging

logging.basicconfig(filename='test.log',level=logging.debug)

logging.info('info test')

logging.warning('warning test')

logging.critical('critical test')

# file content:

# info:root:info test

# warning:root:warning test

# critical:root:critical test

如上所述,我們可以通過basigconfig這個函式進行多種設定,除了上述設定,還可以設定資訊的格式,時間戳以及其格式,檔案模式等,引數如下所示。

上述就是關於logging的基礎用法,至此我們已經可以對乙個程式在logging的模組層面進行日誌記錄,並以特定的格式儲存。下面我們再介紹一些高階一點的用法,以更多更好的滿足我們的工作需求。

高階用法將不再僅僅利用模組層面的函式,而是以幾個基本的物件為基礎:logger物件、handler物件以及formatter物件,有時候還會用大filter物件。在本文中,將主要簡單介紹一下logger、handler和formatter物件。

logger物件通過logging.getlogger(name)構造,其是直接和指令碼進行交流,並傳送源log資訊的物件,其依然是通過debug()、info()這些函式來生成log資訊;handler物件的作用是將logger產生的log資訊進行乙個分發,乙個logger可以新增多個handler物件,從而將log資訊分發到不同的地方;比如,可以將所有log資訊通過filehandler儲存在乙個本地檔案中,同時將warning以上的資訊通過streamhandler輸出到控制台。log資訊的內容和格式是很重要的,因此我們可以通過formatter物件給log資訊設定格式。下面的**展示了這些物件的簡單使用方式。

import logging

logger = logging.getlogger('test')

logger.setlevel(logging.debug)

fh = logging.filehandler('test1.log',mode='a',encoding='utf8')

fh.setlevel(logging.debug)

ch = logging.streamhandler()

ch.setlevel(logging.error)

formatter = logging.formatter('%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s',datefmt='%y-%m-%d %h:%m:%s')

fh.setformatter(formatter)

ch.setformatter(formatter)

logger.addhandler(fh)

logger.addhandler(ch)

日誌資訊的格式設定是很重要的,首先對於message格式的設定是完全和字串的格式化表達一樣的,對格式化表示式內容的填充可以通過info,debug等這些函式的位置引數傳入,比如info(msg_fmt,s1,s2,extra=d),其中msg_fmt是字串格式化表示式,而s1,s2表示對其的內容的填充,最後還有乙個extra引數,其是乙個字典物件,其填充的不是msg_fmt,而是通過formatter物件設定前置格式時需要填充的內容。

對於fromatter物件,我們設定格式時,可以看到其中有一些類似asctime,name,levelname這樣的字串,這些字串實際上是logrecord的屬性,logrecord物件是一條日誌資訊的封裝,每次呼叫info這些介面時會自動生成對應的logrecord物件;參考上述示例**中對於格式的設定,類似'%(cs)-8s'% -->'haha    '  or  '%(cs)8s'%-->'    haha',上述的示例中其中用的括號中的字串實際上都是logrecord的屬性,我們還可以設定其他的屬性,比如行數,以方便我們定位日誌在指令碼中所在的位置,定義的方式實際上就是字串格式化表示式,其中括號表示後續填充內容的字典的key。對於logrecord物件的屬性,可看下圖,我們可以在實際應用中自己利用這些屬性設定格式,以下屬性基本可以滿足我們大部分的需求,當然如果我們有自定義的字段,可以在呼叫info這些介面時通過extra引數進行傳入。

最後還需要說明的一點是,logging是執行緒安全的,即我們可以通過多個執行緒寫入同乙個日誌檔案,其會自動加鎖,但是並不是程序安全的,要實現程序安全,可以參考官方文件,當然,更多的高階功能,也可以參看官方的logging cookbook。

python程式設計之美

許久沒有用python,好多都忘得差不多了,以至於面試 趕緊複習,求下次輕虐。1 cmp list1,list2 比較兩個列表的元素 2 len list 列表元素個數 3 max list 返回列表元素最大值 4 min list 返回列表元素最小值 5 list seq 將元組轉換為列表 2 l...

python程式設計之NMS

非極大值抑制 nms nms的演算法步驟如下 input 所有 出的bounding box bbx 資訊 座標和置信度confidence iou閾值 大於該閾值的bbx將被移除 for object in all objects 1 獲取當前目標類別下所有bbx的資訊 2 將bbx按照confi...

詳解Python中的日誌模組logging

許多應用程式中都會有日誌模組,用於記錄系統在執行過程中的一些關鍵資訊,以便於對系統的執行狀況進行跟蹤。在.net平台中,有非常著名的第三方開源日誌元件log4net,c 中,有人們熟悉的log4cpp,而在python中,我們不需要第三方的日誌元件,因為它已經為我們提供了簡單易用 且功能強大的日誌模...