【问题标题】:Making logging module write all logs to only stderr使日志记录模块将所有日志仅写入stderr
【发布时间】:2019-12-08 10:35:28
【问题描述】:

我正在使用 pytest 来测试产生一些输出的 CLI。在运行测试时,我想将 CLI 的日志级别设置为 DEBUG。但是,我不希望 CLI 日志干扰解析 CLI 输出的测试。

如何使日志记录模块将所有日志仅发送到标准错误?我查看了this 帖子,但它谈到了将日志发送到标准错误除了标准输出。

【问题讨论】:

  • 你试过logger.addHandler(logging.StreamHandler(sys.stderr)吗?
  • (a new comment on purpose)查看docs后,stderr其实是StreamHandlers的默认值。如果您展示了如何配置您的记录器将会很有帮助,因为根据docs,您只需不做任何事情就可以得到您想要的结果
  • pytest 默认会捕获所有输出; capsys 夹具将为您提供捕获的stdout/stderr 输出,而caplog 将捕获日志记录。我不认为你会受到任何干扰。如果我错了,请举一个您无法实现所需行为的测试示例。

标签: python logging pytest stderr


【解决方案1】:

执行与链接答案相同的操作,但将 stdout 替换为 stderr。因此,您将使用 logging.StreamHandler(sys.stderr) 创建一个处理程序,并确保这是唯一的活动处理程序,如果您想专门将日志转到 stderr。

正如@Tomerikoo 正确指出的那样,您不需要做任何事情,尽管日志记录默认使用带有stderr 的StreamHandler。下面代码的唯一真正价值是它设置了一个与默认值不同的级别。只要logging.warning('log') 没有其他设置,就会向标准错误发送日志。

附录:您也可以使用 basicConfig 来减少样板代码。

import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
logging.info('test') # sends log to stderr

【讨论】:

  • 阅读我的cmets上的问题:有趣的事情:sys.stderr实际上是默认StreamHandlerbasicConfig默认创建默认StreamHandler,而@如果未定义处理程序,将自动调用 987654327@。所以基本上这意味着我们可以做logging.info('test'),它会去stderr
【解决方案2】:

您可以将给定记录器的日志输出定向到 stderr,如下所示。这默认使用 stderr 进行输出,但如果您愿意,可以使用 sys.stdout 代替。

import logging
import sys

DEFAULT_LOGGER_NAME = 'default_logger'


def init_logging(logger_name=DEFAULT_LOGGER_NAME,
                 log_level=logging.DEBUG,
                 stream=None):
    # logging
    logger = logging.getLogger(logger_name)
    logger.setLevel(log_level)
    # create formatter
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    # create console handler and set level to debug
    if stream is None:
        stream = sys.stderr
    ch = logging.StreamHandler(stream=stream)
    ch.setLevel(log_level)
    # add formatter to ch
    ch.setFormatter(formatter)
    # add ch to logger
    logger.addHandler(ch)

    return logger

这个函数需要在你的程序开始时被调用(例如ma​​in()的开始)。

然后在代码中,你只需要调用以下代码:

logger = logging.getLogger(LOGGER_NAME) 

【讨论】:

  • 这有一个未使用的导入,更重要的是这个init_logging 函数似乎只是python 已经内置的东西的一个较弱版本:logging.basicConfig
  • 似乎很明显,它需要在程序开始的某个地方在 __main__() 中调用...
  • 但是您正在从函数返回logger。我打算这样做,您可能的意思是:您只需要调用以下内容: logger = init_logging() ...
  • 为清晰起见进行了编辑。您只需要预先调用一次 init_logging() (是的,它返回记录器,但这并不意味着它应该在代码中的任何地方调用)。在其他任何地方,您都应该调用 logging.getLogger(LOGGER_NAME),因为此时已经配置了记录器。
猜你喜欢
  • 2016-12-29
  • 2015-02-25
  • 2014-02-01
  • 2020-11-07
  • 2020-08-16
  • 2022-07-06
  • 2017-06-04
  • 2011-09-17
  • 1970-01-01
相关资源
最近更新 更多