首页 > 解决方案 > 如何访问 python LogRecord 的 asctime?

问题描述

我有一个记录器和一个 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 属性。我发现的唯一类似于我的问题说

要设置消息和 asctime,您必须首先在 emit 方法中调用 self.format(record)

但是当您以我的方式指定日志字符串时,logging.Formatter 不会这样做%(asctime)s吗?

编辑: running.t 是对的,我只是不明白文档的含义。我通过将我的格式化程序添加到我的过滤器并在开头调用格式化函数来解决它:

 def __init__(self, formatter):
     self.msgs = {}
     self.formatter = formatter

 def filter(self, record):
     self.formatter.format(record)

标签: pythonlogging

解决方案


在pyton 日志记录模块文档的过滤对象部分中,我发现了以下注释:

请注意,附加到处理程序的过滤器会在处理程序发出事件之前进行咨询,而附加到记录器的过滤器会在每次记录事件时(使用 debug()、info() 等)在向处理程序发送事件之前进行咨询。这意味着由后代记录器生成的事件不会被记录器的过滤器设置过滤,除非过滤器也已应用于这些后代记录器。

您的过滤器被添加到记录器,而格式化程序被添加到处理程序。因此,我认为您的filter方法在您指定的任何格式化程序之前应用。

顺便说一句,你不应该DuplicateFilter继承自logging.Filter吗?


推荐阅读