Python logging 模塊詳解

Python logging 模塊定義了爲應用程序和庫實現靈活的事件日誌記錄的函數和類。

程序開發過程中,很多程序都有記錄日誌的需求,並且日誌包含的信息有正常的程序訪問日誌還可能有錯誤、警告等信息輸出,Python 的 logging 模塊提供了標準的日誌接口,可以通過它存儲各種格式的日誌,日誌記錄提供了一組便利功能,用於簡單的日誌記錄用法。

  • 使用 Python Logging 模塊的主要好處是所有 Python 模塊都可以參與日誌記錄

  • Logging 模塊提供了大量具有靈活性的功能

日誌記錄函數以它們用來跟蹤的事件的級別或嚴重性命名。下面描述了標準級別及其適用性(從高到低的順序):

日誌等級(level) 描述
DEBUG 最詳細的日誌信息,典型應用場景是 問題診斷
INFO 信息詳細程度僅次於DEBUG,通常只記錄關鍵節點信息,用於確認一切都是按照我們預期的那樣進行工作
WARNING 當某些不期望的事情發生時記錄的信息(如,磁盤可用空間較低),但是此時應用程序還是正常運行的
ERROR 由於一個更嚴重的問題導致某些功能不能正常運行時記錄的信息
CRITICAL 當發生嚴重錯誤,導致應用程序不能繼續運行時記錄的信息

日誌級別等級排序:critical > error > warning > info > debug

級別越高打印的日誌越少,反之亦然,即

  • debug    : 打印全部的日誌( notset 等同於 debug )

  • info     : 打印 info, warning, error, critical 級別的日誌

  • warning  : 打印 warning, error, critical 級別的日誌

  • error    : 打印 error, critical 級別的日誌

  • critical : 打印 critical 級別

一、 Logging 模塊日誌記錄方式

Logging 模塊提供了兩種日誌記錄方式:

  • 一種方式是使用 Logging 提供的模塊級別的函數

  • 另一種方式是使用 Logging 日誌系統的四大組件記錄

1、Logging 定義的模塊級別函數

函數 說明
logging.debug(msg, *args, **kwargs) 創建一條嚴重級別爲DEBUG的日誌記錄
logging.info(msg, *args, **kwargs) 創建一條嚴重級別爲INFO的日誌記錄
logging.warning(msg, *args, **kwargs) 創建一條嚴重級別爲WARNING的日誌記錄
logging.error(msg, *args, **kwargs) 創建一條嚴重級別爲ERROR的日誌記錄
logging.critical(msg, *args, **kwargs) 創建一條嚴重級別爲CRITICAL的日誌記錄
logging.log(level, *args, **kwargs) 創建一條嚴重級別爲level的日誌記錄
logging.basicConfig(**kwargs) 對root logger進行一次性配置

簡單打印日誌:

import logging
# 打印日誌級別def test_logging():    logging.debug('Python debug')    logging.info('Python info')    logging.warning('Python warning')    logging.error('Python Error')    logging.critical('Python critical')
test_logging()

輸出結果:

WARNING:root:Python warningERROR:root:Python ErrorCRITICAL:root:Python critical

當指定一個日誌級別之後,會記錄大於或等於這個日誌級別的日誌信息,小於的將會被丟棄, ==默認情況下日誌打印只顯示大於等於 WARNING 級別的日誌。==

1.1 設置日誌顯示級別

通過 logging.basicConfig() 可以設置 root 的日誌級別,和日誌輸出格式。

logging.basicConfig() 關鍵字參數

關鍵字 描述
filename 創建一個 FileHandler,使用指定的文件名,而不是使用 StreamHandler。
filemode 如果指明瞭文件名,指明打開文件的模式(如果沒有指明 filemode,默認爲 'a')。
format handler 使用指明的格式化字符串。
datefmt handler 使用指明的格式化字符串。
level 指明根 logger 的級別。
stream 使用指明的流來初始化 StreamHandler。該參數與 'filename' 不兼容,如果兩個都有,'stream' 被忽略。

format 格式

格式 描述
%(levelno)s 打印日誌級別的數值
%(levelname)s 打印日誌級別名稱
%(pathname)s 打印當前執行程序的路徑
%(filename)s 打印當前執行程序名稱
%(funcName)s 打印日誌的當前函數
%(lineno)d 打印日誌的當前行號
%(asctime)s 打印日誌的時間
%(thread)d 打印線程 ID
%(threadName)s 打印線程名稱
%(process)d 打印進程 ID
%(message)s 打印日誌信息

注意:Logging.basicConfig() 需要在開頭就設置,在中間設置並無作用

實例

import logging
# 打印日誌級別def test():    logging.basicConfig(level=logging.DEBUG)    logging.debug('Python debug')    logging.info('Python info')    logging.warning('Python warning')    logging.error('Python Error')    logging.critical('Python critical')    logging.log(2,'test')test()

輸出:

DEBUG:root:Python debugINFO:root:Python infoWARNING:root:Python warningERROR:root:Python ErrorCRITICAL:root:Python critical

1.2 將日誌信息記錄到文件

# 日誌信息記錄到文件logging.basicConfig(filename='F:/example.log', level=logging.DEBUG)logging.debug('This message should go to the log file')logging.info('So should this')logging.warning('And this, too')

在相應的路徑下會有 example.log 日誌文件,內容如下:

DEBUG:root:This message should go to the log fileINFO:root:So should thisWARNING:root:And this, too

1.3 多個模塊記錄日誌信息

如果程序包含多個模塊,則用以下實例來顯示日誌信息:實例中有兩個模塊,一個模塊通過導入另一個模塊的方式用日誌顯示另一個模塊的信息:

myapp.py 模塊

import loggingimport mylibdef main():    logging.basicConfig(filename='myapp.log',level=logging.DEBUG)    logging.info('Started')    mylib.do_something()    logging.info('Finished')
if __name__ == '__main__':    main()

mylib.py 模塊

import logging
def do_something():    logging.info('Doing something')

執行 myapp.py 模塊會打印相應日誌,在文件 myapp.log 中顯示信息如下:​​​​​​​

INFO:root:StartedINFO:root:Doing somethingINFO:root:Finishe

1.4 顯示信息的日期及更改顯示消息格式

顯示消息日期​​​​​​​

import logging# 顯示消息時間logging.basicConfig(format='%(asctime)s %(message)s')logging.warning('is when this event was logged.')
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')logging.warning('is when this event was logged.')

結果:​​​​​​​

2019-10-16 18:57:45,988 is when this event was logged.2019-10-16 18:57:45,988 is when this event was logged.

更改顯示消息格式​​​​​​​

import logging# 更改顯示消息的格式logging.basicConfig(format='%(levelname)s:%(message)s',level=logging.DEBUG)logging.debug('Python message format Debug')logging.info('Python message format Info')logging.warning('Python message format Warning')

結果:​​​​​​​

DEBUG:Python message format DebugINFO:Python message format InfoWARNING:Python message format Warning

==注意==:顯示結果只顯示級別和具體信息,之前顯示的 “根” 已經消失,重新定義的格式修改了默認輸出方式。

2、logging 模塊四大組件

組件名稱 對應類名 功能描述
日誌器 Logger 暴露函數給應用程序,基於日誌記錄器和過濾器級別決定哪些日誌有效
處理器 Handler 將 logger 創建的日誌記錄發送到合適的目的輸出
過濾器 Filter 提供了更細粒度的控制工具來決定輸出哪條日誌記錄,丟棄哪條日誌記錄
格式器 Formatter 決定日誌記錄的最終輸出格式

2.1 日誌器- Logger

Logger 持有日誌記錄器的方法,日誌記錄器不直接實例化,而是通過模塊級函數 logger.getlogger (name) 來實例化,使用相同的名稱多次調用 getLogger() 總是會返回對相同 Logger 對象的引用。

  • 應用程序代碼能直接調用日誌接口。

  • Logger最常用的操作有兩類:配置和發送日誌消息。

  • 初始化 logger = logging.getLogger("endlesscode"),獲取 logger 對象,getLogger() 方法後面最好加上所要日誌記錄的模塊名字,配置文件和打印日誌格式中的 %(name)s 對應的是這裏的模塊名字,如果不指定name則返回root對象。

  • logger.setLevel(logging.DEBUG),Logging 中有 NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL這幾種級別,日誌會記錄設置級別以上的日誌

  • 多次使用相同的name調用 getLogger 方法返回同一個 looger 對象;

Logger是一個樹形層級結構,在使用接口 debug,info,warn,error,critical 之前必須創建 Logger 實例:

  •  
創建方法: logger = logging.getLogger(logger_name)

創建Logger實例後,可以使用以下方法進行日誌級別設置,增加處理器 Handler:

  • logger.setLevel(logging.ERROR) # 設置日誌級別爲 ERROR,即只有日誌級別大於等於 ERROR 的日誌纔會輸出

  • logger.addHandler(handler_name) # 爲 Logger 實例增加一個處理器

  • logger.removeHandler(handler_name) # 爲 Logger 實例刪除一個處理器

2.2 處理器- Handler

Handler 處理器類型有很多種,比較常用的有三個,StreamHandler,FileHandler,NullHandler

StreamHandler

  •  
創建方法:sh = logging.StreamHandler(stream=None)

創建 StreamHandler 之後,可以通過使用以下方法設置日誌級別,設置格式化器 Formatter,增加或刪除過濾器 Filter:​​​​​​​

ch.setLevel(logging.WARN) # 指定日誌級別,低於WARN級別的日誌將被忽略
ch.setFormatter(formatter_name) # 設置一個格式化器formatter
ch.addFilter(filter_name) # 增加一個過濾器,可以增加多個 ch.removeFilter(filter_name) # 刪除一個過濾器

2.3 過濾器- Filter

Handlers 和 Loggers 可以使用 Filters 來完成比級別更復雜的過濾。Filter 基類只允許特定 Logger 層次以下的事件。例如用 ‘A.B’ 初始化的 Filter 允許Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’ 等記錄的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。如果用空字符串來初始化,所有的事件都接受。

創建方法: filter = logging.Filter(name='')

2.4 格式器- Formatter

使用Formatter對象設置日誌信息最後的規則、結構和內容,默認的時間格式爲%Y-%m-%d %H:%M:%S。

創建方法: formatter = logging.Formatter(fmt=None, datefmt=None)

其中,fmt 是消息的格式化字符串,datefmt 是日期字符串。如果不指明 fmt,將使用 '%(message)s' 。如果不指明  datefmt,將使用 ISO8601 日期格式。

2.5 組件之間的關聯關係

  • 日誌器(logger)需要通過處理器(handler)將日誌信息輸出到目標位置,不同的處理器(handler)可以將日誌輸出到不同的位置;

  • 日誌器(logger)可以設置多個處理器(handler)將同一條日誌記錄輸出到不同的位置;

  • 每個處理器(handler)都可以設置自己的過濾器(filter)實現日誌過濾,從而只保留感興趣的日誌;

  • 每個處理器(handler)都可以設置自己的格式器(formatter)實現同一條日誌以不同的格式輸出到不同的地方。

簡明瞭說就是:日誌器(logger)是入口,真正幹活兒的是處理器(handler),處理器(handler)還可以通過過濾器(filter)和格式器(formatter)對要輸出的日誌內容做過濾和格式化等處理操作。

  • Logger 可以包含一個或多個 Handler 和 Filter

  • Logger 與 Handler 或 Fitler 是一對多的關係

  • 一個 Logger 實例可以新增多 個 Handler,一個 Handler 可以新增多個格式化器或多個過濾器,而且日誌級別將會繼承。

二、Logging 日誌工作流程

1、Logging 模塊使用過程

1)第一次導入 logging 模塊或使用 reload 函數重新導入 logging 模塊,logging 模塊中的代碼將被執行,這個過程中將產生 logging 日誌系統的默認配置。

2)自定義配置(可選),logging標準模塊支持三種配置方式: dictConfig,fileConfig,listen。其中,dictConfig 是通過一個字典進行配置 Logger,Handler,Filter,Formatter;fileConfig 則是通過一個文件進行配置;而 listen 則監聽一個網絡端口,通過接收網絡數據來進行配置。當然,除了以上集體化配置外,也可以直接調用 Logger,Handler 等對象中的方法在代碼中來顯式配置。

3)使用 logging 模塊的全局作用域中的 getLogger 函數來得到一個 Logger 對象實例(其參數即是一個字符串,表示 Logger 對象實例的名字,即通過該名字來得到相應的 Logger 對象實例)。

4)使用 Logger 對象中的 debug,info,error,warn,critical 等方法記錄日誌信息。

2、Logging 模塊處理流程

                                            logging 處理流程

流程描述:

  1. 判斷日誌的等級是否大於 Logger 對象的等級,如果大於,則往下執行,否則,流程結束。

  2. 產生日誌:第一步,判斷是否有異常,如果有,則添加異常信息。第二步,處理日誌記錄方法(如 debug,info 等)中的佔位符,即一般的字符串格式化處理。

  3. 使用註冊到 Logger 對象中的 Filters 進行過濾。如果有多個過濾器,則依次過濾;只要有一個過濾器返回假,則過濾結束,且該日誌信息將丟棄,不再處理,而處理流程也至此結束。否則,處理流程往下執行。

  4. 在當前 Logger 對象中查找 Handlers,如果找不到任何 Handler,則往上到該 Logger 對象的父 Logger 中查找;如果找到一個或多個 Handler,則依次用 Handler 來處理日誌信息。但在每個 Handler 處理日誌信息過程中,會首先判斷日誌信息的等級是否大於該 Handler 的等級,如果大於,則往下執行(由 Logger 對象進入 Handler 對象中),否則,處理流程結束。

  5. 執行 Handler 對象中的 filter 方法,該方法會依次執行註冊到該 Handler 對象中的 Filter。如果有一個 Filter 判斷該日誌信息爲假,則此後的所有 Filter 都不再執行,而直接將該日誌信息丟棄,處理流程結束。

  6. 使用 Formatter 類格式化最終的輸出結果。注:Formatter 同上述第 2 步的字符串格式化不同,它會添加額外的信息,比如日誌產生的時間,產生日誌的源代碼所在的源文件的路徑等等。

  7. 真正地輸出日誌信息(到網絡,文件,終端,郵件等)。至於輸出到哪個目的地,由 Handler 的種類來決定。

三、配置日誌

程序員可以通過三種方式配置日誌記錄:

1、使用配置方法的 Python 代碼顯式創建記錄器,處理程序和格式化程序。

2、創建日誌記錄配置文件並使用該 fileConfig() 功能讀取它。

3、創建配置信息字典並將其傳遞給 dictConfig()函數。

下面使用 Python 代碼配置一個非常簡單的記錄器,一個控制檯處理程序和一個簡單的格式化程序:

logging.conf 配置文件:​​​​​​​​​​​​​​

[loggers]keys=root,simpleExample
[handlers]keys=consoleHandler
[formatters]keys=simpleFormatter
[logger_root]level=DEBUGhandlers=consoleHandler
[logger_simpleExample]level=DEBUGhandlers=consoleHandlerqualname=simpleExamplepropagate=0
[handler_consoleHandler]class=StreamHandlerlevel=DEBUGformatter=simpleFormatterargs=(sys.stdout,)
[formatter_simpleFormatter]format=%(asctime)s - %(name)s - %(levelname)s - %(message)sdatefmt=

config_logging.py 配置器:​​​​​​​

import logging# create loggerlogger = logging.getLogger('simple_example')logger.setLevel(logging.DEBUG)
# create console handler and set level to debugch = logging.StreamHandler()ch.setLevel(logging.DEBUG)
# create formatterformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to chch.setFormatter(formatter)
# add ch to loggerlogger.addHandler(ch)
# 'application' codelogger.debug('debug message')logger.info('info message')logger.warning('warn message')logger.error('error message')logger.critical('critical message')

recorder 記錄器:​​​​​​​

import loggingimport logging.config
logging.config.fileConfig('logging.conf')
# create loggerlogger = logging.getLogger('simpleExample')
# 'application' codelogger.debug('debug message')logger.info('info message')logger.warning('warn message')logger.error('error message')logger.critical('critical message')

運行結果:​​​​​​​

2019-10-16 19:45:34,440 - simple_example - DEBUG - debug message2019-10-16 19:45:34,440 - simple_example - INFO - info message2019-10-16 19:45:34,440 - simple_example - WARNING - warn message2019-10-16 19:45:34,440 - simple_example - ERROR - error message2019-10-16 19:45:34,441 - simple_example - CRITICAL - critical message

總結

本章節給大家介紹了 Python 標準庫中 Logging 模塊的詳細介紹與使用,對 Python 工程師使用該模塊提供更好的支撐

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章