【问题标题】:Logging messages appear twice in console Python日志消息在控制台 Python 中出现两次
【发布时间】:2013-06-20 08:05:33
【问题描述】:

我发现this 回答了一个看似相似的问题,但是(因为我是 Python 新手)我不确定如何在我的代码中实现这个解决方案(如果它毕竟是同一个问题)。

在我的代码中,我有以下部分:

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                    filename='C:\\Tests\\TRACE.log',
                    filemode='a')
console = logging.StreamHandler()
console.setLevel(logging.INFO)
consoleFormatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(consoleFormatter)
logging.getLogger('').addHandler(console)
localLog = logging.getLogger('text')

有趣的是,它过去可以正常工作,但有时它开始将这些重复的消息写入控制台。

有人可以给我指路吗?

【问题讨论】:

  • 虽然这是一篇旧文章,但请将输出添加到 OP。否则很难辨别具体问题是什么以及如何解决。

标签: python logging jython


【解决方案1】:

通常会出现重复的日志语句,因为附加了两个单独的处理程序,它们将您的日志语句定向到同一个位置。有几件事值得尝试找到问题的根源:

  1. 注释掉对 logging.basicConfig 的调用 - 如果这消除了重复的日志语句,那么这意味着您可能不需要手动配置第二个日志处理程序。
  2. 如果您使用的是 IDE,可能值得在日志语句中设置断点,并使用调试器单步执行,这样您就可以检查 python 日志设置的状态,从而更清楚地了解附加了哪些不同的处理程序。

为了使您的日志记录更易于管理,可能值得考虑将配置从代码中移出并放入配置文件 - logging configuration 上的 Python 文档是一个很好的起点。

【讨论】:

  • 您好,感谢您的回答,但我如何才能注释掉所有 loggingBasicConfig?它包括路径、格式和文件模式等强制性设置...
  • 从阅读问题来看,问题似乎是您在控制台中收到重复的日志消息,而文件日志记录不是问题。我怀疑 basicConfig 正在设置控制台日志处理程序,然后您正在设置第二个控制台日志处理程序。强烈建议将日志记录配置移动到配置文件中,您可以在其中更明确地了解特定设置。
  • 值得指出的一点是,记录到文件、控制台或任何其他目的地不是强制性的——记录只是将消息引导到有用的地方以查看或存储它们的一种方式,并且有您可能希望将它们发送到许多不同的地方(文件和控制台是两个非常常见的选项)。强烈建议您通过 python 文档中的advanced logging tutorial 深入了解日志记录的工作原理。
【解决方案2】:

看来我已经弄清楚了这个问题的根源了。

问题是我曾经在模块级别获取记录器。它看起来很合乎逻辑,但有一个陷阱——Python 日志记录模块会在您从文件加载配置之前尊重所有创建的记录器。所以基本上,当我将一个模块(它在内部使用获取记录器)导入到主代码(我也在其中调用记录器)时,它导致记录器数据流式传输两次。

这个问题的可能解决方案是:

  1. 不要在模块级别获取记录器
  2. disable_existing_loggers 设置为False自 Python 2.7 起添加

【讨论】:

    【解决方案3】:

    我的记录器配置也遇到了同样的情况,我使用的修复是:

    class Logger:
    
    @staticmethod
    def setup(name, file_name):
    
        log_file = <path to save the file>
        log_file_max_size = 1024 * 1024 * 20  # megabytes
        log_num_backups = 3
        log_format = "%(asctime)s [%(levelname)s]: %(filename)s(%(funcName)s:%(lineno)s) >> %(message)s"
        log_filemode = "w"  # w: overwrite; a: append
        logging.basicConfig(filename=log_file, format=log_format, filemode=log_filemode, level=logging.DEBUG)
        rotate_file = logging.handlers.RotatingFileHandler(
            log_file, maxBytes=log_file_max_size, backupCount=log_num_backups
        )
        logger = logging.getLogger(name)
        # Console output line.
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        log_formatter = logging.Formatter(log_format)
        console_handler.setFormatter(log_formatter)
        logger.handlers = rotate_file, console_handler
    
        return logger
    

    【讨论】:

      猜你喜欢
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 2014-10-22
      • 2020-02-25
      • 2015-07-29
      • 2016-02-14
      相关资源
      最近更新 更多