程序開發過程中,很多程序都有記錄日志的需求,並且日志包含的信息有正常的程序訪問日志還可能有錯誤、警告等信息輸出。
python默認的print方法可以打印程序的日志,但是無法滿足我們工作中對日志存儲、展示更深層的需求。
本文介紹一個python常用的日志庫"logging",接下來我們就看看如何使用吧~
Python的logging模塊定義了為應用程序和庫實現靈活的事件日志記錄的函數和類。
Python的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的日志信息才會輸出),日志格式如下圖所示:
問題來了,日志級別等級及設置是怎樣的?
怎樣設置日志的輸出方式?比如輸出到日志文件中?
簡單配置日志級別
#!/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是一個樹形層級結構,在使用接口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處理器類型有很多種,比較常用的有三個,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)
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')