我有一个记录器和一个DuplicateFilter类,它可以过滤已经记录一次的消息。我想将日志记录到过滤器中的时间包括在内,但是当我尝试访问属性asctime时,我得到:AttributeError: 'LogRecord' object has no attribute 'asctime'
下面是我设置记录器的一个小例子:
import logging
import logging.handlers as log_handlers
def setup_logger(filename):
class DuplicateFilter(object):
def __init__(self):
self.msgs = set()
def filter(self, record):
if logger.level == 10:
return True
rv = True
try:
print(record.asctime)
msg = record.threadName + " " + record.msg
if msg in self.msgs:
rv = False
except Exception as e:
print(traceback.format_exc())
return rv
self.msgs.add(msg)
return rv
log_formatter = logging.Formatter("%(asctime)s [%(levelname)-5.5s] [%(threadName)-30.30s] %(message)s")
file_handler = log_handlers.TimedRotatingFileHandler(filename, encoding="UTF-8", when='W6', backupCount=12)
file_handler.setFormatter(log_formatter)
console_handler = logging.StreamHandler()
console_handler.setFormatter(log_formatter)
logger = logging.getLogger(filename)
logger.propagate = False
logger.addHandler(console_handler)
logger.addHandler(file_handler)
logger.setLevel(logging.INFO)
dup_filter = DuplicateFilter()
logger.addFilter(dup_filter)
return logger
log = setup_logger("test.log")
for i in range(3):
log.info("wow")
现在,我的记录如下所示:2018-07-18 14:34:49,642 [INFO ] [MainThread ] wow
它们显然具有一个asctime,我在Formatter的构造函数中显式设置了asctime属性。我发现的唯一与我类似的question说
要设置消息和asctime,必须首先在发出方法内调用self.format(record)
但是当您指定日志字符串时,logging.Formatter不会像我对%(asctime)s
所做的那样吗?
编辑:running.t是正确的,我只是不理解文档的含义。我通过将格式化程序添加到过滤器中并在开始时调用format函数来解决了这个问题:
def __init__(self, formatter):
self.msgs = {}
self.formatter = formatter
def filter(self, record):
self.formatter.format(record)
答案 0 :(得分:1)
在pyton日志记录模块文档的filter objects section中,我发现以下注释:
请注意,在处理程序发出事件之前,请先咨询附加到处理程序的过滤器,而无论何时记录事件(使用debug(),info()等),都应查询附加到记录器的过滤器,之前发送事件给处理程序。这意味着由后代记录器生成的事件将不会被记录器的过滤器设置过滤,除非该过滤器也已应用于这些后代记录器。
您的过滤器已添加到记录器,而格式化程序已添加到处理程序。因此,我认为您的filter
方法是在您指定的任何格式化程序之前应用的。
顺便说一句,您的DuplicateFilter
是否应该从logging.Filter
继承?