前言
程式開發過程中,很多程式都有記錄日志的需求,并且日志包含的資訊有正常的程式通路日志還可能有錯誤、警告等資訊輸出。
python預設的print方法可以列印程式的日志,但是無法滿足我們工作中對日志存儲、展示更深層的需求。
本文介紹一個python常用的日志庫"logging",接下來我們就看看如何使用吧~

logging介紹
Python的logging子產品定義了為應用程式和庫實作靈活的事件日志記錄的函數和類。
Python的logging 子產品提供了标準的日志接口,可以通過它存儲各種格式的日志,日志記錄提供了一組便利功能,用于簡單的日志記錄用法。
logging安裝
pip3 install logging
複制
簡單使用
代碼如下:
#!/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')
複制
預設情況下,logging子產品将日志列印到螢幕上(stdout),日志級别為WARNING(即隻有日志級别高于WARNING的日志資訊才會輸出),日志格式如下圖所示:
問題來了,日志級别等級及設定是怎樣的?
怎樣設定日志的輸出方式?比如輸出到日志檔案中?
簡單配置
簡單配置日志級别
- 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,内容如下:
因為通過level=logging.INFO設定日志級别為INFO,是以所有的日志資訊均輸出出來了。
問題又來了。
通過上述配置方法都可以配置哪些資訊?
Logger,Handler,Formatter,Filter
幾個重要的概念
- 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)
複制
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='')
複制
代碼如下:
# -*- 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如下:
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
複制
代碼如下:
# -*- 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')
複制