运行logging.basicConfig之前的Python日志记录?

时间:2009-12-22 01:46:53

标签: python logging

如果您调用logging.info() BEFORE ,则运行logging.basicConfig,logging.basicConfig调用似乎没有任何效果。实际上,没有记录。

这种行为记录在哪里?我真的不明白。

6 个答案:

答案 0 :(得分:45)

您可以删除默认处理程序并重新配置日志记录,如下所示:

# if someone tried to log something before basicConfig is called, Python creates a default handler that
# goes to the console and will ignore further basicConfig calls. Remove the handler if there is one.
root = logging.getLogger()
if root.handlers:
    for handler in root.handlers:
        root.removeHandler(handler)
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)

答案 1 :(得分:10)

您已要求记录某些内容。因此,日志记录必须构建默认配置。一旦配置了日志......好吧......它已经配置好了。

  

“配置了记录器对象,   以下方法创建日志   提示:“

此外,您可以阅读有关创建处理程序以防止虚假日志记录的信息。但对于糟糕的实施而言,这不仅仅是一种有用的技术。

这是一个诀窍。

  1. 除了logging.getlogger()请求之外,任何模块都无法执行任何操作。

  2. 只有if __name__ == "__main__":才能进行日志记录配置。

  3. 如果您在模块中进行全局级别的日志记录,则可以强制日志记录来构建它的默认配置。

    不要在任何模块中全局logging.info。如果您绝对认为模块中的全局级别必须logging.info,则必须在进行导入之前配置日志。这会导致令人不快的脚本。

答案 2 :(得分:8)

Carlos A. Ibarra的答案原则上是正确的,但是由于您正在迭代可能通过调用removeHandler()而更改的列表,因此实现可能会中断。这是不安全的。 两种选择是:

while len(logging.root.handlers) > 0:
    logging.root.removeHandler(logging.root.handlers[-1])
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)

或:

logging.root.handlers = []
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)

这两个中的第一个使用循环是最安全的(因为可以在日志框架内显式调用处理程序的任何破坏代码)。不过,这是一个黑客攻击,因为我们依赖于logging.root.handlers作为列表。

答案 3 :(得分:1)

今天遇到了同样的问题,作为上述答案的替代方案,这是我的解决方案。

import logging
import sys

logging.debug('foo') # IRL, this call is from an imported module

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO, force=True)
    logging.info('bar') # without force=True, this is not printed to the console

以下是 docs 关于 force 参数的说明。

<块引用>

如果此关键字参数指定为 true,则任何现有处理程序 附加到根记录器被移除并关闭,然后携带 输出其他参数指定的配置。

答案 4 :(得分:0)

@ paul-kremer给出的答案的更干净的版本是:

while len(logging.root.handlers):
    logging.root.removeHandler(logging.root.handlers[-1])

注意:通常可以假设logging.root.handlers始终是列表(请参阅:https://github.com/python/cpython/blob/cebe9ee988837b292f2c571e194ed11e7cd4abbb/Lib/logging/init.py#L1253

答案 5 :(得分:0)

这就是我所做的。

我想登录到一个在配置文件中配置了名称的文件,并获取配置解析的调试日志。

TL;博士;这会记录到缓冲区中,直到配置记录器的所有内容都可用

# Log everything into a MemoryHandler until the real logger is ready.
# The MemoryHandler never flushes (flushLevel 100 is above CRITICAL) automatically but only on close.
# If the configuration was loaded successfully, the real logger is configured and set as target of the MemoryHandler
# before it gets flushed by closing.
# This means, that if the log gets to stdout, it is unfiltered by level
root_logger = logging.getLogger()
root_logger.setLevel(logging.NOTSET)
stdout_logging_handler = logging.StreamHandler(sys.stderr)
tmp_logging_handler = logging.handlers.MemoryHandler(1024 * 1024, 100, stdout_logging_handler)
root_logger.addHandler(tmp_logging_handler)

config: ApplicationConfig = ApplicationConfig.from_filename('config.ini')

# because the records are already logged, unwanted ones need to be removed
filtered_buffer = filter(lambda record: record.levelno >= config.main_config.log_level, tmp_logging_handler.buffer)
tmp_logging_handler.buffer = filtered_buffer

root_logger.removeHandler(tmp_logging_handler)
logging.basicConfig(filename=config.main_config.log_filename, level=config.main_config.log_level, filemode='wt')
logging_handler = root_logger.handlers[0]
tmp_logging_handler.setTarget(logging_handler)
tmp_logging_handler.close()
stdout_logging_handler.close()