在Python編程中,日志記錄是一種重要的調試和錯誤追蹤工具。Python的logging模塊提供了一種靈活的框架,用于發出日志消息,這些消息可以被發送到各種輸出源,如控制臺、文件、HTTP GET/POST位置等。本文將深入探討Python的logging模塊,包括其基本用法、高級特性以及如何將其應用到實際項目中。
首先,我們來看一下logging模塊的基本用法。logging模塊的主要功能是提供一種靈活的框架,用于發出日志消息。這些消息可以被發送到各種輸出源,如控制臺、文件、HTTP GET/POST位置等。logging模塊的核心是Logger類,它提供了應用程序可直接使用的接口。Logger實例化后,可以設置其日志級別(DEBUG, INFO, WARNING, ERROR, CRITICAL),并可以通過其方法來發出日志消息。
例如,以下是一個簡單的logging模塊的使用示例:
import logging# 創建一個logger
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)# 創建一個handler,用于寫入日志文件
fh = logging.FileHandler('test.log')
fh.setLevel(logging.DEBUG)# 定義handler的輸出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)# 給logger添加handler
logger.addHandler(fh)# 記錄一條日志
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')
在這個示例中,我們首先創建了一個名為’my_logger’的logger,并設置了其日志級別為DEBUG。然后,我們創建了一個handler,用于將日志消息寫入到’test.log’文件中。我們還定義了handler的輸出格式,包括時間戳、logger的名字、日志級別和日志消息。最后,我們將這個handler添加到logger中,并發出了幾條不同級別的日志消息。
除了基本的用法,logging模塊還提供了許多高級特性,如過濾器、格式化器、處理器等。過濾器可以根據日志消息的內容或級別來決定是否應該處理這條消息。格式化器可以定義日志消息的輸出格式。處理器則負責將日志消息發送到指定的輸出源。
例如,以下是如何使用過濾器和格式化器的示例:
import logging# 創建一個logger
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)# 創建一個handler,用于寫入日志文件
fh = logging.FileHandler('test.log')
fh.setLevel(logging.DEBUG)# 創建一個過濾器,只處理INFO級別及以上的日志消息
class MyFilter(logging.Filter):def filter(self, record):return record.levelno >= logging.INFO
filter = MyFilter()
fh.addFilter(filter)# 定義handler的輸出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)# 給logger添加handler
logger.addHandler(fh)# 記錄一條INFO級別的日志消息和一條DEBUG級別的日志消息
logger.info('This is an info message')
logger.debug('This is a debug message') # 這條消息不會被處理,因為它的級別低于INFO
在這個示例中,我們首先創建了一個名為’my_logger’的logger,并設置了其日志級別為DEBUG。然后,我們創建了一個handler,用于將日志消息寫入到’test.log’文件中。我們還創建了一個過濾器,只處理INFO級別及以上的日志消息。最后,我們將這個handler添加到logger中,并發出了兩條不同級別的日志消息。由于我們的過濾器只處理INFO級別及以上的日志消息,所以DEBUG級別的日志消息不會被處理。
本專欄封裝日志工具類供外部使用:
配置文件
BASE:log_level: "debug"fh_file_log_level: "debug" #生產環境換成warninglog_extension: ".log"test:url: "http://119.3.246.198:64644"
配置文件調用代碼更新
import os
from utils.YamlUtil import YamlReadercurrent = os.path.abspath(__file__)BASE_DIR = os.path.dirname(os.path.dirname(current))_config_path = BASE_DIR + os.sep + "config"
_config_file = _config_path + os.sep + 'conf.yml'_log_path = BASE_DIR + os.sep + "logs"
def get_config_path():return _config_pathdef get_config_file():return _config_filedef get_log_path():return _log_path
class ConfigYaml:def __init__(self):self.config = YamlReader(get_config_file()).data()def get_conf_url(self):return self.config['BASE']['test']['url']def get_conf_log_level(self):#獲取日志級別return self.config['BASE']['log_level']def get_conf_fh_file_log_level(self):#獲取日志文件級別return self.config['BASE']['fh_file_log_level']def get_conf_log_extension(self):#獲取日志文件擴展名return self.config['BASE']['log_extension']
日志工具類封裝
import logging
import datetime,os
from config import Conf
from config.Conf import ConfigYamllog_levels = {"info": logging.INFO,"debug": logging.DEBUG,"warning": logging.WARNING,"error": logging.ERROR,
}class Logger:def __init__(self, log_file, log_name, log_level, fh_file_log_level):self.log_file = log_fileself.log_name = log_nameself.log_level = log_levelself.fh_file_log_level = fh_file_log_levelself.logger = logging.getLogger(self.log_name)self.logger.setLevel(log_levels[self.log_level])if not self.logger.handlers:fh_stream = logging.StreamHandler()fh_stream.setLevel(log_levels[self.log_level])formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')fh_stream.setFormatter(formatter)fh_file = logging.FileHandler(self.log_file,encoding='utf-8') #注意,此處不寫encoding='utf-8',會出現導出日志中的中文亂碼。fh_file.setLevel(log_levels[self.fh_file_log_level])fh_file.setFormatter(formatter)self.logger.addHandler(fh_stream)self.logger.addHandler(fh_file)log_path = Conf.get_log_path()
current_time = datetime.datetime.now().strftime("%Y-%m-%d")
conf_read = ConfigYaml()
log_extention = conf_read.get_conf_log_extension()
log_file =os.path.join(log_path,current_time+log_extention)
log_level = conf_read.get_conf_log_level()
fh_file_log_level = conf_read.get_conf_fh_file_log_level()def tester_log(log_name = __file__):return Logger(log_file=log_file, log_name=log_name, log_level=log_level, fh_file_log_level=fh_file_log_level).logger
這段代碼是一個Python日志記錄模塊的實現。它使用了logging
庫來創建和管理日志記錄器,并提供了自定義的日志級別和格式。
首先,導入了必要的模塊:
logging
:用于創建和管理日志記錄器。datetime
和os
:用于獲取當前時間和構建文件路徑。Conf
和ConfigYaml
:從配置文件中讀取配置信息。
然后,定義了一個名為Logger
的類,用于創建和管理日志記錄器。該類接受以下參數:
log_file
:日志文件的路徑。log_name
:日志記錄器的名稱。log_level
:日志記錄器的級別。fh_file_log_level
:文件處理器的日志級別。
在類的構造函數中,首先根據傳入的參數創建一個日志記錄器對象,并設置其級別。然后,如果日志記錄器沒有處理程序(handler),則創建一個流處理器(StreamHandler)和一個文件處理器(FileHandler)。流處理器將日志輸出到控制臺,而文件處理器將日志寫入指定的文件中。
接下來,定義了一些變量和常量:
log_path
:日志文件所在的目錄路徑。current_time
:當前時間的字符串表示形式,格式為"YYYY-MM-DD"。conf_read
:一個ConfigYaml
對象,用于讀取配置文件中的配置信息。log_extention
:日志文件的擴展名。log_file
:完整的日志文件路徑。log_level
:日志記錄器的級別。fh_file_log_level
:文件處理器的日志級別。
最后,定義了一個名為tester_log
的函數,用于創建并返回一個日志記錄器對象。該函數接受一個可選參數log_name
,默認值為當前文件的名稱。
使用這個模塊,你可以創建一個日志記錄器對象,并通過調用其方法來記錄不同級別的日志消息。例如,可以使用logger.info()
、logger.debug()
、logger.warning()
或logger.error()
來記錄不同級別的日志消息。
工具類應用
在requests封裝類中對requests添加日志
import requests
from utils.LogUtil import tester_log
class Request:def __init__(self):self.log = tester_log()def requests_api(self, url, data=None, json=None, headers=None, cookies=None, method="get"):if method == "get":self.log.debug("發送get請求")r = requests.get(url, data=data, json=json, headers=headers, cookies=cookies)elif method == "post":self.log.debug("發送post請求")r = requests.post(url, data=data, json=json, headers=headers, cookies=cookies)code = r.status_codetry:body = r.json()except Exception as e:body = r.textres = dict()res["code"] = coderes["body"] = bodyreturn resdef get(self, url, **kwargs):return self.requests_api(url, method="get", **kwargs)def post(self, url, **kwargs):return self.requests_api(url, method="post", **kwargs)
調用效果
def login():conf_y = ConfigYaml()r = Request()url_path = conf_y.get_conf_url()url = url_path+'/prod-api/login'data = {"username":"test","password":"49e881218a48a363c35c5215fdc80d3f48d6a17ba0a1f9242c66aebc7ea29c626b26d7ef3bdae00ee9fde85bbf837dcce9f9e4e8f4371d74ff6eaf98ab53d7715996761ef56bff06461e74eb4b3f582949fb3b5281a89fc997a1de35f86a9aad35b87980dcf94e43191293"}res=r.requests_api(url,json=data,method="post")# r = requests.post(url,json=data)print(res)if __name__ == '__main__':login()
總的來說,Python的logging模塊提供了一種靈活的框架,用于發出日志消息。通過使用logging模塊,我們可以方便地記錄和管理程序的運行情況,從而更好地進行調試和錯誤追蹤。雖然logging模塊的基本用法相對簡單,但其高級特性卻非常強大,可以幫助我們更有效地使用日志記錄。因此,對于任何使用Python進行開發的程序員來說,理解和掌握logging模塊都是非常必要的。