導入 logging 模塊
import logging
日志級別
DEBUG
- 詳細信息,典型地調試問題時會感興趣
INFO
- 證明事情按預期工作
WARNING
- 表明發生了一些意外
- 或者不久的將來會發生問題(如‘磁盤滿了’)
- 但是軟件還是在正常工作
ERROR
- 由於更嚴重的問題,軟件已不能執行一些功能了
CRITICAL
- 嚴重錯誤,表明軟件已不能繼續運行了
logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')
配置
# 通過下面的方式進行簡單配置輸出方式與日志級別 logging.basicConfig(filename='logger.log', level=logging.INFO)
幾個重要的概念
- Logger,記錄器,暴露了應用程序代碼能直接使用的接口。
- Handler,處理器,將(記錄器產生的)日志記錄發送至合適的目的地。
- Filter,過濾器,提供了更好的粒度控制,它可以決定輸出哪些日志記錄。
- Formatter,格式化器,指明了最終輸出中日志記錄的布局。
Logger 記錄器
- Logger 是一個樹形層級結構
- 在使用接口 debug,info,warning,error,critical 之前必須創建 Logger 實例
- 即創建一個記錄器
- 如果沒有顯式的進行創建,則默認創建一個 root logger
- 並應用默認的日志級別(WARNING)
- 處理器 Handler(StreamHandler,即將日志信息打印輸出在標准輸出上)
- 格式化器 Formatter(默認的格式即為第一個簡單使用程序中輸出的格式)
logger = logging.getLogger(logger_name) # 設置日志級別為ERROR,即只有日志級別大於等於ERROR的日志才會輸出 logger.setLevel(logging.ERROR) # 為Logger實例增加一個處理器 logger.addHandler(handler_name) # 為Logger實例刪除一個處理器 logger.removeHandler(handler_name)
Handler 處理器
Handler 處理器類型有很多種,比較常用的有三個
StreamHandler
FileHandler
NullHandler
sh = logging.StreamHandler(stream=None) fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False) # NullHandler類位於核心logging包,不做任何的格式化或者輸出 # 本質上它是個“什么都不做”的handler,由庫開發者使用 nf = logging.NullHandler()
創建 StreamHandler 之后
- 可以通過使用以下方法設置日志級別
- 設置格式化器 Formatter
- 增加或刪除過濾器 Filter
# 指定日志級別,低於 WARNING 級別的日志將被忽略 handler.setLevel(logging.WARNING) # 設置一個格式化器 formatter handler.setFormatter(formatter_name) # 增加一個過濾器,可以增加多個 handler.addFilter(filter_name) # 刪除一個過濾器 handler.removeFilter(filter_name)
Formatter 格式化器
- 使用 Formatter 對象設置日志信息最后的規則、結構和內容
- 默認的時間格式為
%Y-%m-%d %H:%M:%S
# fmt是消息的格式化字符串,如果不指明fmt,將使用'%(message)s' # datefmt是日期字符串,如果不指明datefmt,將使用ISO8601日期格式。 formatter = logging.Formatter(fmt=None, datefmt=None)
Filter 過濾器
- Handlers 和 Loggers 可以使用 Filters 來完成比級別更復雜的過濾
- Filter 基類只允許特定 Logger 層次以下的事件
filter = logging.Filter(name='')
import logging # create logger logger_name = "example" logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) # create file handler log_path = "demo03.log" fh = logging.FileHandler(log_path) fh.setLevel(logging.WARNING) # 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.warning('warning message') logger.error('error message') logger.critical('critical message')
配置方式
- 顯式創建記錄器 Logger、處理器 Handler 和格式化器 Formatter,並進行相關設置
- 通過簡單方式進行配置,使用
basicConfig()
函數直接進行配置 - 通過配置文件進行配置,使用
fileConfig()
函數讀取配置文件 - 通過配置字典進行配置,使用
dictConfig()
函數讀取配置信息 - 通過網絡進行配置,使用
listen()
函數進行網絡配置
basicConfig 關鍵字參數
filename
- 創建一個 FileHandler,使用指定的文件名,而不是使用 StreamHandler
filemode
- 如果指明了文件名,指明打開文件的模式(如果沒有指明 filemode,默認為
a
)
- 如果指明了文件名,指明打開文件的模式(如果沒有指明 filemode,默認為
format
- handler 使用指明的格式化字符串
datefmt
- 使用指明的日期/時間格式
level
- 指明根 logger 的級別
stream
- 使用指明的流來初始化 StreamHandler,該參數與
filename
不兼容, - 如果兩個都有,
stream
被忽略
- 使用指明的流來初始化 StreamHandler,該參數與
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 格式
%a
,本地的縮寫工作日名稱%A
,本地的完整工作日名稱%b
,本地的縮寫月份名稱%B
,本地的全月名稱%c
,本地的適當日期和時間表示%d
,每月的一天作為小數 [01,31]%H
,小時(24 小時時鍾)作為小數 [00,23]%I
,小時(12 小時時鍾)作為小數目 [01,12]%j
,一年中的一天作為小數 [001,366]%m
,月作為小數 [01,12]%M
,分鍾作為小數 [00,59]%p
,本地相當於上午或下午%S
,第二為小數 [00,61]%U
,年度周數(星期日為一周的第一天)為小數 [00,53]- 第一個星期天前的新年中的所有日子都被認為是在第 0 周
%w
,平日作為小數 [0 (星期日), 6]%W
,年度周數(星期一為一周的第一天)為小數 [00,53]- 第一個星期一之前的新年的所有日子都被認為是在第 0 周
%x
,本地的適當日期表示%X
,本地的適當時間表示%y
,沒有世紀的年份作為小數 [00,99]%Y
,以世紀為小數的年份%Z
,時區名稱(如果沒有時區,則不存在字符)%%
,字面意思%
[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=form01 args=(sys.stderr,) [handler_hand02] class=FileHandler level=DEBUG formatter=form02 args=('demo04.log', 'a') [formatters] keys=form01,form02 [formatter_form01] format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s [formatter_form02] format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
log.py文件
import logging import logging.config logging.config.fileConfig("logging.conf") # create logger logger_name = 'example01' logger = logging.getLogger(logger_name) logger.debug('debug message') logger.info('info message') logger.warning('warning message') logger.error('error message') logger.critical('critical message')