python logging模塊使用簡介
1.簡單使用
#!/usr/local/bin/python
# -*- coding:utf-8 -*-
import logging
logging.debug(‘debug message‘)
logging.info(‘info message‘)
logging.warn(‘warn message‘)
logging.error(‘error message‘)
logging.critical(‘critical message‘)
輸出:
WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message
默認情況下,logging模塊將日誌打印到屏幕上(stdout),日誌級別為WARNING(即只有日誌級別高於WARNING的日誌信息才會輸出),日誌格式如下圖所示:
default_logging_format.png問題來了
- 日誌級別等級及設置是怎樣的?
- 怎樣設置日誌的輸出方式?比如輸出到日誌文件中?
2.簡單配置
日誌級別
級別 | 何時使用 |
---|---|
DEBUG | 詳細信息,典型地調試問題時會感興趣。 |
INFO | 證明事情按預期工作。 |
WARNING | 表明發生了一些意外,或者不久的將來會發生問題(如‘磁盤滿了’)。軟件還是在正常工作。 |
ERROR | 由於更嚴重的問題,軟件已不能執行一些功能了。 |
CRITICAL | 嚴重錯誤,表明軟件已不能繼續運行了。 |
簡單配置
#!/usr/local/bin/python
# -*- coding:utf-8 -*-
import logging
# 通過下面的方式進行簡單配置輸出方式與日誌級別
logging.basicConfig(filename=‘logger.log‘, level=logging.INFO)
logging.debug(‘debug message‘)
logging.info(‘info message‘)
logging.warn(‘warn message‘)
logging.error(‘error message‘)
logging.critical(‘critical message‘)
輸出:
標準輸出(屏幕)未顯示任何信息,發現當前工作目錄下生成了logger.log,內容如下:
INFO:root:info message
WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message
因為通過level=logging.INFO設置日誌級別為INFO,所以所有的日誌信息均輸出出來了。
問題又來了
- 通過上述配置方法都可以配置那些信息?
在解決以上問題之前,需要先了解幾個比較重要的概念,Logger,Handler,Formatter,Filter
3.幾個重要的概念
- Logger 記錄器,暴露了應用程序代碼能直接使用的接口。
- Handler 處理器,將(記錄器產生的)日誌記錄發送至合適的目的地。
- Filter 過濾器,提供了更好的粒度控制,它可以決定輸出哪些日誌記錄。
- Formatter 格式化器,指明了最終輸出中日誌記錄的布局。
Logger 記錄器
Logger是一個樹形層級結構,在使用接口debug,info,warn,error,critical之前必須創建Logger實例,即創建一個記錄器,如果沒有顯式的進行創建,則默認創建一個root logger,並應用默認的日誌級別(WARN),處理器Handler(StreamHandler,即將日誌信息打印輸出在標準輸出上),和格式化器Formatter(默認的格式即為第一個簡單使用程序中輸出的格式)。
創建方法:
logger = logging.getLogger(logger_name)
創建Logger實例後,可以使用以下方法進行日誌級別設置,增加處理器Handler。
- logger.setLevel(logging.ERROR) # 設置日誌級別為ERROR,即只有日誌級別大於等於ERROR的日誌才會輸出
- logger.addHandler(handler_name) # 為Logger實例增加一個處理器
- logger.removeHandler(handler_name) # 為Logger實例刪除一個處理器
Handler 處理器
Handler處理器類型有很多種,比較常用的有三個,StreamHandler,FileHandler,NullHandler,詳情可以訪問Python logging.handlers
創建StreamHandler之後,可以通過使用以下方法設置日誌級別,設置格式化器Formatter,增加或刪除過濾器Filter。
- ch.setLevel(logging.WARN) # 指定日誌級別,低於WARN級別的日誌將被忽略
- ch.setFormatter(formatter_name) # 設置一個格式化器formatter
- ch.addFilter(filter_name) # 增加一個過濾器,可以增加多個
- ch.removeFilter(filter_name) # 刪除一個過濾器
StreamHandler
創建方法:
sh = logging.StreamHandler(stream=None)
FileHandler
創建方法:
fh = logging.FileHandler(filename, mode=‘a‘, encoding=None, delay=False)
NullHandler
NullHandler類位於核心logging包,不做任何的格式化或者輸出。
本質上它是個“什麽都不做”的handler,由庫開發者使用。
Formatter 格式化器
使用Formatter對象設置日誌信息最後的規則、結構和內容,默認的時間格式為%Y-%m-%d %H:%M:%S。
創建方法:
formatter = logging.Formatter(fmt=None, datefmt=None)
其中,fmt是消息的格式化字符串,datefmt是日期字符串。如果不指明fmt,將使用‘%(message)s‘。如果不指明datefmt,將使用ISO8601日期格式。
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=‘‘)
以下是相關概念總結:
element_relation.jpg熟悉了這些概念之後,有另外一個比較重要的事情必須清楚,即Logger是一個樹形層級結構;
Logger可以包含一個或多個Handler和Filter,即Logger與Handler或Fitler是一對多的關系;
一個Logger實例可以新增多個Handler,一個Handler可以新增多個格式化器或多個過濾器,而且日誌級別將會繼承。
4.Logging工作流程
logging模塊使用過程
- 第一次導入logging模塊或使用reload函數重新導入logging模塊,logging模塊中的代碼將被執行,這個過程中將產生logging日誌系統的默認配置。
- 自定義配置(可選)。logging標準模塊支持三種配置方式: dictConfig,fileConfig,listen。其中,dictConfig是通過一個字典進行配置Logger,Handler,Filter,Formatter;fileConfig則是通過一個文件進行配置;而listen則監聽一個網絡端口,通過接收網絡數據來進行配置。當然,除了以上集體化配置外,也可以直接調用Logger,Handler等對象中的方法在代碼中來顯式配置。
- 使用logging模塊的全局作用域中的getLogger函數來得到一個Logger對象實例(其參數即是一個字符串,表示Logger對象實例的名字,即通過該名字來得到相應的Logger對象實例)。
- 使用Logger對象中的debug,info,error,warn,critical等方法記錄日誌信息。
logging模塊處理流程
logging_flow.png- 判斷日誌的等級是否大於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的種類來決定。
註:以上內容摘抄自第三條參考資料,內容略有改動,轉載特此聲明。
再看日誌配置
5.配置方式
- 顯式創建記錄器Logger、處理器Handler和格式化器Formatter,並進行相關設置;
- 通過簡單方式進行配置,使用basicConfig()函數直接進行配置;
- 通過配置文件進行配置,使用fileConfig()函數讀取配置文件;
- 通過配置字典進行配置,使用dictConfig()函數讀取配置信息;
- 通過網絡進行配置,使用listen()函數進行網絡配置。
basicConfig關鍵字參數
關鍵字 | 描述 |
---|---|
filename | 創建一個FileHandler,使用指定的文件名,而不是使用StreamHandler。 |
filemode | 如果指明了文件名,指明打開文件的模式(如果沒有指明filemode,默認為‘a‘)。 |
format | handler使用指明的格式化字符串。 |
datefmt | 使用指明的日期/時間格式。 |
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 | 打印日誌信息 |
有用的datefmt格式
參考time.strftime
配置示例
顯式配置
使用程序logger.py如下:
# -*- encoding:utf-8 -*-
import logging
# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
# create file handler
log_path = "./log.log"
fh = logging.FileHandler(log_path)
fh.setLevel(logging.WARN)
# create formatter
fmt = "%(asctime)-15s %(levelname)s %(filename)s %(lineno)d %(process)d %(message)s"
datefmt = "%a %d %b %Y %H:%M:%S"
formatter = logging.Formatter(fmt, datefmt)
# add handler and formatter to logger
fh.setFormatter(formatter)
logger.addHandler(fh)
# print log info
logger.debug(‘debug message‘)
logger.info(‘info message‘)
logger.warn(‘warn message‘)
logger.error(‘error message‘)
logger.critical(‘critical message‘)```
##### 文件配置
配置文件logging.conf如下:
```[loggers]
keys=root,example01
[logger_root]
level=DEBUG
handlers=hand01,hand02
[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0
[handlers]
keys=hand01,hand02
[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=(‘log.log‘, ‘a‘)
[formatters]
keys=form01,form02
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s```
使用程序logger.py如下:
```#!/usr/bin/python
# -*- encoding:utf-8 -*-
import logging
import logging.config
logging.config.fileConfig("./logging.conf")
# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)
logger.debug(‘debug message‘)
logger.info(‘info message‘)
logger.warn(‘warn message‘)
logger.error(‘error message‘)
logger.critical(‘critical message‘)```
本文轉自: https://www.jianshu.com/p/feb86c06c4f4
python logging模塊使用簡介