一 分模块解读
1.1 导入模块
- logging: Python 标准库中的日志模块,用于记录日志。
- RotatingFileHandler:
logging.handlers
中的类,用于创建滚动日志文件。 - os: 用于处理文件和目录操作。
import logging
from logging.handlers import RotatingFileHandler
import os
1.2 设置过滤条件 (LoggerFilter 类)
-
init: 初始化过滤器,接受三个参数
log_name
,total_log
, 和data_log
。log_name
: 该过滤器应用于的日志名称。total_log
: 记录总日志的日志名称。data_log
: 记录数据日志的日志名称。
-
filter: 根据日志记录的名称进行过滤。
- 如果
log_name
是total_log
,则过滤掉data_log
的日志记录。 - 否则,只保留
data_log
的日志记录。
- 如果
class LoggerFilter(logging.Filter):
def __init__(self, log_name, total_log, data_log):
super().__init__(log_name)
self.log_name = log_name
self.total_log = total_log
self.data_log = data_log
def filter(self, record):
if self.log_name == self.total_log:
return record.name != self.data_log
return record.name == self.data_log
1.3 filter_logging 函数
- log_folder: 日志文件存储目录。如果目录不存在,则创建该目录。
def filter_logging(total_log, data_log, log_level=logging.INFO):
"""
初始化日志配置,将日志输出到文件和控制台
"""
log_folder = './log_file'
if not os.path.exists(log_folder):
os.makedirs(log_folder)
log_formatter: 配置日志格式。
%(asctime)s
: 日志事件的时间戳。%(msecs)03d
: 毫秒部分,3位数字。%(levelname)s
: 日志级别名称。%(name)s
: 日志记录器的名称。%(lineno)d
: 产生日志记录的代码行号。%(filename)s
: 产生日志记录的文件名。%(message)s
: 日志消息。
log_formatter = logging.Formatter(
'[%(asctime)s.%(msecs)03d] [%(levelname)s] [%(name)s] [line:%(lineno)d] '
'%(filename)s: \t%(message)s', datefmt='%Y-%m-%d %H:%M:%S'
)
console_handler: 配置控制台日志处理器。
- 设置日志格式。
- 设置日志级别。
console_handler = logging.StreamHandler()
console_handler.setFormatter(log_formatter)
console_handler.setLevel(log_level)
- loggers: 包含总日志和数据日志的文件路径。
- file_handlers: 用于存储文件处理器。
loggers = {
total_log: f'{log_folder}/{total_log}.log',
data_log: f'{log_folder}/{data_log}.log'
}
file_handlers = []
- RotatingFileHandler: 创建滚动日志文件处理器。
log_file
: 日志文件路径。mode='a'
: 追加模式。maxBytes=int(1e7)
: 每个日志文件最大10MB。backupCount=7
: 保留7个旧文件。
- addFilter: 为文件处理器添加过滤器。
- file_handlers.append: 将文件处理器添加到列表中
for logger_name, log_file in loggers.items():
file_handler = RotatingFileHandler(log_file, mode='a', maxBytes=int(1e7), backupCount=7)
file_handler.setFormatter(log_formatter)
file_handler.setLevel(log_level)
file_handler.addFilter(LoggerFilter(logger_name, total_log, data_log))
file_handlers.append(file_handler)
logging.basicConfig: 配置全局日志系统。
- 设置日志级别。
- 设置日期格式。
- 添加处理器(控制台和文件处理器)。
logging.basicConfig(level=log_level,
datefmt='%Y-%m-%d %H:%M:%S',
handlers=[console_handler] + file_handlers
)
- main_logger: 获取或创建名为
total_log
的日志记录器实例。 - logging.info: 记录一条 "Start write logging" 信息。
main_logger = logging.getLogger(total_log)
logging.info("Start write logging")
return main_logger
1.4 示例
- filter_logging: 调用
filter_logging
函数,初始化日志系统。 - total_logger: 获取或创建名为
total_log
的日志记录器实例,记录不同级别的日志消息。 - data_logger: 获取或创建名为
data_log
的日志记录器实例,记录不同级别的日志消息。
这个代码配置了一个日志系统,能够将日志消息按不同的名称过滤到不同的文件中,同时在控制台输出。
if __name__ == "__main__":
main_logger = filter_logging("total_log", "data_log", logging.INFO)
total_logger = logging.getLogger("total_log")
total_logger.info("This is an info message for total_log")
total_logger.debug("This is a debug message for total_log")
total_logger.error("This is an error message for total_log")
data_logger = logging.getLogger("data_log")
data_logger.info("This is an info message for data_log")
data_logger.debug("This is a debug message for data_log")
data_logger.error("This is an error message for data_log")
二 完整日志写入格式代码
为了确保将基础配置应用到全局日志系统,可以在 filter_logging
函数中使用 logging.basicConfig
方法进行配置。需要注意的是,basicConfig
只能配置一次,所以要确保在首次配置时包括所有必要的处理程序。
import logging
from logging.handlers import RotatingFileHandler
import os
class LoggerFilter(logging.Filter):
def __init__(self, log_name, total_log, data_log):
super().__init__(log_name)
self.log_name = log_name
self.total_log = total_log
self.data_log = data_log
def filter(self, record):
if self.log_name == self.total_log:
return record.name != self.data_log
return record.name == self.data_log
def filter_logging(total_log, data_log, log_level=logging.INFO):
"""
初始化日志配置,将日志输出到文件和控制台
"""
log_folder = './log_file'
# 如果文件夹不存在,创建文件夹
if not os.path.exists(log_folder):
os.makedirs(log_folder)
# 配置日志格式
log_formatter = logging.Formatter(
'[%(asctime)s.%(msecs)03d] [%(levelname)s] [%(name)s] [line:%(lineno)d] '
'%(filename)s: \t%(message)s', datefmt='%Y-%m-%d %H:%M:%S'
)
# 创建控制台日志处理器
console_handler = logging.StreamHandler()
console_handler.setFormatter(log_formatter)
console_handler.setLevel(log_level)
# 配置文件日志处理器
loggers = {
total_log: f'{log_folder}/{total_log}.log',
data_log: f'{log_folder}/{data_log}.log'
}
file_handlers = []
for logger_name, log_file in loggers.items():
file_handler = RotatingFileHandler(log_file, mode='a', maxBytes=int(1e7), backupCount=7)
file_handler.setFormatter(log_formatter)
file_handler.setLevel(log_level)
file_handler.addFilter(LoggerFilter(logger_name, total_log, data_log))
file_handlers.append(file_handler)
# 将配置应用到全局日志系统
logging.basicConfig(level=log_level,
datefmt='%Y-%m-%d %H:%M:%S',
handlers=[console_handler] + file_handlers # encoding='utf-8'
)
main_logger = logging.getLogger(total_log)
logging.info("Start write logging")
return main_logger
# 示例
if __name__ == "__main__":
main_logger = filter_logging("total_log", "data_log", logging.INFO)
total_logger = logging.getLogger("total_log")
total_logger.info("This is an info message for total_log")
total_logger.debug("This is a debug message for total_log")
total_logger.error("This is an error message for total_log")
data_logger = logging.getLogger("data_log")
data_logger.info("This is an info message for data_log")
data_logger.debug("This is a debug message for data_log")
data_logger.error("This is an error message for data_log")