1. 程式人生 > 實用技巧 >python--使用logging庫自定義日誌輸出

python--使用logging庫自定義日誌輸出

前言

  1. 現在要求將錯誤日誌寫入日誌檔案,通過查詢日誌檔案的方式,可以檢視最新用例的執行情況,並快速定位問題
  2. 使用print能夠將一些錯誤資訊輸出在螢幕上,但是無法寫入在檔案中
  3. 本篇部落格介紹如何使用logging庫實現日誌輸出

logging庫

logging日誌級別

debug info warning error critical

logging簡單示例

  1. loggin預設只輸出 級別為warning error critical的日誌
  2. logging.basicConfig(**kwargs) 控制著logging的行為,其中level=[]控制日誌輸出等級
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug('這是一個debug級別的資訊,一般用來列印一些除錯資訊,級別最低')
logging.info('這是一個info級別的資訊,一般用來列印一些正常的操作資訊')
logging.warning('這是一個warning級別的資訊')
logging.error('這是一個error級別的資訊')
logging.critical('這是一個critical級別的資訊,一般用來列印一些致命的錯誤資訊,等級最高')

logging.basicConfig(**kwargs)引數

  • filename:指定日誌檔名
  • filemode:和file函式意義相同,指定日誌檔案的開啟模式,'w'或者'a'
  • format:指定輸出的格式和內容,format可以輸出很多有用的資訊
'''
formatter = logging.Formatter('%(asctime)s-%(levelname)s-%(filename)s-日誌資訊:%(message)s')

%(name)s            logger的名字(常用)
%(levelno)s         數字形式的日誌級別
%levelname()s       文字形式的日誌級別(常用)
%pathname()s        呼叫日誌輸出函式模組的完整路徑名,可能沒有(常用)
%filename()s        呼叫日誌輸出函式的檔名(常用)
%(module)s          呼叫日誌輸出函式的函式名
%(funcName)s        呼叫日誌輸出函式語句的
%(lineno)d          呼叫日誌輸出函式語句的程式碼行
%(created)f         當前時間,用unix標準表示
%(relativeCreated)d 輸出日誌資訊時間,自logger建立以來的毫秒數
%(asctime)s         字串形式的當前時間,預設格式‘2000-01-01 10:00:00,100’
%(thread)d          執行緒ID,可能沒有
%(threadName)s      執行緒名,可能沒有
%(process)d         程序ID,可能沒有
%(message)s         使用者輸出的訊息(常用)
'''
  • datefmt:指定時間格式,同time.strftime()
  • level:設定日誌級別,預設為logging.WARNNING
  • stream:指定將日誌的輸出流,可以指定輸出到sys.stderr,sys.stdout或者檔案,預設輸出到sys.stderr,當stream和filename同時指定時,stream被忽略

haddler種類

logging是通過addHandler新增主處理物件,haddler種類有:

'''
handler名稱:位置;作用

StreamHandler:logging.StreamHandler     日誌輸出到流,可以是sys.stderr,sys.stdout或者檔案
FileHandler:logging.FileHandler     日誌輸出到檔案
BaseRotatingHandler:logging.handlers.BaseRotatingHandler    基本的日誌回滾方式
RotatingHandler:logging.handlers.RotatingHandler    日誌回滾方式,支援日誌檔案最大數量和日誌檔案回滾
TimeRotatingHandler:logging.handlers.TimeRotatingHandler    日誌回滾方式,在一定時間區域內回滾日誌檔案
SocketHandler:logging.handlers.SocketHandler    遠端輸出日誌到TCP/IP sockets
DatagramHandler:logging.handlers.DatagramHandler    遠端輸出日誌到UDP sockets
SMTPHandler:logging.handlers.SMTPHandler    遠端輸出日誌到郵件地址
SysLogHandler:logging.handlers.SysLogHandler    日誌輸出到syslog
NTEventLogHandler:logging.handlers.NTEventLogHandler    遠端輸出日誌到Windows NT/2000/XP的事件日誌
MemoryHandler:logging.handlers.MemoryHandler    日誌輸出到記憶體中的指定buffer
HTTPHandler:logging.handlers.HTTPHandler    通過"GET"或者"POST"遠端輸出到HTTP伺服器
'''

輸出日誌在控制檯和文字中示例

# File  : test.py
# IDE   : PyCharm

import sys
import logging

logger = logging.getLogger(__name__)
logger.setLevel(level = logging.DEBUG)   # 輸出等級
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')   # 輸出格式

handler = logging.FileHandler("log.txt")    # 文字輸出
handler.setFormatter(formatter)
console = logging.StreamHandler(sys.stdout)   # 控制檯輸出
console.setFormatter(formatter)

logger.addHandler(handler)
logger.addHandler(console)

if __name__ == '__main__':
    logger.info("這是一條info級別資訊")
    logger.debug("這是一條debug級別資訊")
    logger.warning("這是一條warning級別資訊")

執行結果

封裝日誌處理

# File  : logger_operation.py
# IDE   : PyCharm

import os
import sys
import logging
from time import strftime

class Logger():
    def __init__(self):
        # 日誌格式
        custom_format = '%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s'
        # 日期格式
        date_format = '%a, %d %b %Y %H:%M:%S'
        # 日誌路徑
        log_path = os.path.abspath('.') + '/logs/'

        self._logger = logging.getLogger()  # 例項化
        self.filename = '{0}{1}.log'.format(log_path, strftime("%Y-%m-%d")) # 日誌檔名
        self.formatter = logging.Formatter(fmt=custom_format, datefmt=date_format)
        self._logger.addHandler(self._get_file_handler(self.filename))
        self._logger.addHandler(self._get_console_handler())
        self._logger.setLevel(logging.INFO)  # 預設等級

    def _get_file_handler(self, filename):
        '''輸出到日誌檔案'''
        filehandler = logging.FileHandler(filename, encoding="utf-8")
        filehandler.setFormatter(self.formatter)
        return filehandler

    def _get_console_handler(self):
        '''輸出到控制檯'''
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(self.formatter)
        return console_handler

    @property
    def logger(self):
        return self._logger

if __name__ == '__main__':
    import datetime
    logging=Logger().logger
    logging.info(u"{}:執行xxx用例".format(datetime.datetime.now()))

總結

  1. 本篇部落格只實現了logging庫的基本使用,呼叫起來可能會不夠靈活,可以通過讀取配置檔案的方式去配置日誌
  2. 日誌是為了方便除錯和查錯,在必要的函式內,都需要加上日誌