【问题标题】:Logging with two handlers - one to file and one to stderr使用两个处理程序进行日志记录 - 一个到文件,一个到 stderr
【发布时间】:2019-08-17 13:37:30
【问题描述】:

我有以下代码来创建两个日志记录处理程序。目标是让stream_handler 只写入sterr,而file_handler 只写入文件。

在下面的代码中,stream_handler 也会写入文件,所以每当我记录一条消息时,我都会有重复的日志条目。如何修改它以使 stream_handler not 写入文件?

def create_timed_rotating_log(
        name='log',
        path='logs/',
        when='D',
        interval=1,
        backupCount=30,
        form='%(asctime)s | %(name)s |  %(levelname)s: %(message)s',
        sterr = False,
        verbose=False):

  logger = logging.getLogger(name)
  formatter = logging.Formatter(form)
  logger.setLevel(logging.DEBUG)

  if sterr:
      stream_handler = logging.StreamHandler()
      stream_handler.setLevel(logging.DEBUG if verbose else logging.ERROR)
      stream_handler.setFormatter(formatter)
      logger.addHandler(stream_handler)

  file_handler = TimedRotatingFileHandler(filename=path+name,
                                          when=when,
                                          interval=interval,
                                          backupCount=backupCount)
  file_handler.setFormatter(formatter)
  file_handler.setLevel(logging.DEBUG if verbose else logging.ERROR)
  logger.addHandler(file_handler)

  return logger

【问题讨论】:

    标签: python logging error-logging


    【解决方案1】:

    看起来您已经考虑将消息作为重复发送到两个处理程序。如果您希望文件不接收消息并且它们仅转到 stderr,则当 stderr=True 时,您永远不要将添加文件处理程序的代码放在 else 中,以便仅在 stderr=False 时添加它

    具体来说:

    if sterr:
        stream_handler = logging.StreamHandler()
        stream_handler.setLevel(logging.DEBUG if verbose else logging.ERROR)
        stream_handler.setFormatter(formatter)
        logger.addHandler(stream_handler)
    else:
        file_handler = TimedRotatingFileHandler(filename=path+name,
                                              when=when,
                                              interval=interval,
                                              backupCount=backupCount)
        file_handler.setFormatter(formatter)
        file_handler.setLevel(logging.DEBUG if verbose else logging.ERROR)
        logger.addHandler(file_handler)
    

    我认为这是可能的,但与设置处理程序的更常见问题相比不太可能,当您应该如何使用日志记录时,在主模块中您将处理程序添加到根记录器,然后只获取记录器当前模块通过logger = logging.getLogger(__name__)。这和import logging 是唯一应该出现在除if __name__=="__main__": 出现的模块之外的任何模块中的日志记录代码,之后它应该设置日志记录。


    出现重复的唯一方法是在程序中调用该函数两次。问题不在于这两个处理程序,而是来自第二次调用此设置函数的其他两个处理程序。

    您只需将处理程序添加到根记录器一次,而不是为每个模块中的每个记录器添加一次。

    【讨论】:

    • 我想如果你用 sterr 和 verbose == True 运行它,你会发现情况并非如此
    • 你的程序调用create_timed_rotating_log多少次?
    • 仅一次...然后我使用返回的记录器对象使用 .info、debig 等写入消息;
    • 看起来您已经考虑将消息作为重复发送到两个处理程序。如果您希望文件不接收消息并且它们仅转到 stderr,则当 stderr=True 时,您永远不要将添加文件处理程序的代码放在 else 中,以便仅在 stderr=False 时添加它
    【解决方案2】:

    不完全确定为什么会这样,但首先添加 StreamHandler 会导致它也写入文件。添加 TimedRotatingFileHandler 后,我将 StreamHandler 移至,这解决了问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-27
      • 1970-01-01
      • 2023-03-23
      • 2017-02-15
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多