使用两个处理程序进行日志记录 - 一个用于文件,一个用于 stderr

Logging with two handlers - one to file and one to stderr

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

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

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

您似乎已经考虑过将消息发送到两个处理程序是重复的。如果您希望文件不接收消息并且它们只转到 stderr,当 stderr=True 时,您永远不要将添加文件处理程序的代码放在 else 中,以便仅在 stderr=False[=14= 时才添加它]

具体来说:

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__": 出现的模块中的唯一日志记录代码,紧接着它应该设置日志记录。


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

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

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