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 warning
ERROR:root:Python Error
CRITICAL: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 debug
INFO:root:Python info
WARNING:root:Python warning
ERROR:root:Python Error
CRITICAL: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 file
INFO:root:So should this
WARNING:root:And this, too
1.3 多個模塊記錄日誌信息
如果程序包含多個模塊,則用以下實例來顯示日誌信息:實例中有兩個模塊,一個模塊通過導入另一個模塊的方式用日誌顯示另一個模塊的信息:
myapp.py 模塊
import logging
import mylib
def 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:Started
INFO:root:Doing something
INFO: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 Debug
INFO:Python message format Info
WARNING: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 處理流程
流程描述:
-
判斷日誌的等級是否大於 Logger 對象的等級,如果大於,則往下執行,否則,流程結束。
-
產生日誌:第一步,判斷是否有異常,如果有,則添加異常信息。第二步,處理日誌記錄方法(如 debug,info 等)中的佔位符,即一般的字符串格式化處理。
-
使用註冊到 Logger 對象中的 Filters 進行過濾。如果有多個過濾器,則依次過濾;只要有一個過濾器返回假,則過濾結束,且該日誌信息將丟棄,不再處理,而處理流程也至此結束。否則,處理流程往下執行。
-
在當前 Logger 對象中查找 Handlers,如果找不到任何 Handler,則往上到該 Logger 對象的父 Logger 中查找;如果找到一個或多個 Handler,則依次用 Handler 來處理日誌信息。但在每個 Handler 處理日誌信息過程中,會首先判斷日誌信息的等級是否大於該 Handler 的等級,如果大於,則往下執行(由 Logger 對象進入 Handler 對象中),否則,處理流程結束。
-
執行 Handler 對象中的 filter 方法,該方法會依次執行註冊到該 Handler 對象中的 Filter。如果有一個 Filter 判斷該日誌信息爲假,則此後的所有 Filter 都不再執行,而直接將該日誌信息丟棄,處理流程結束。
-
使用 Formatter 類格式化最終的輸出結果。注:Formatter 同上述第 2 步的字符串格式化不同,它會添加額外的信息,比如日誌產生的時間,產生日誌的源代碼所在的源文件的路徑等等。
-
真正地輸出日誌信息(到網絡,文件,終端,郵件等)。至於輸出到哪個目的地,由 Handler 的種類來決定。
三、配置日誌
程序員可以通過三種方式配置日誌記錄:
1、使用配置方法的 Python 代碼顯式創建記錄器,處理程序和格式化程序。
2、創建日誌記錄配置文件並使用該 fileConfig() 功能讀取它。
3、創建配置信息字典並將其傳遞給 dictConfig()函數。
下面使用 Python 代碼配置一個非常簡單的記錄器,一個控制檯處理程序和一個簡單的格式化程序:
logging.conf 配置文件:
[loggers]
keys=root,simpleExample
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
config_logging.py 配置器:
import logging
# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
recorder 記錄器:
import logging
import logging.config
logging.config.fileConfig('logging.conf')
# create logger
logger = logging.getLogger('simpleExample')
# 'application' code
logger.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 message
2019-10-16 19:45:34,440 - simple_example - INFO - info message
2019-10-16 19:45:34,440 - simple_example - WARNING - warn message
2019-10-16 19:45:34,440 - simple_example - ERROR - error message
2019-10-16 19:45:34,441 - simple_example - CRITICAL - critical message
總結
本章節給大家介紹了 Python 標準庫中 Logging 模塊的詳細介紹與使用,對 Python 工程師使用該模塊提供更好的支撐