如果您调用logging.info() BEFORE ,则运行logging.basicConfig,logging.basicConfig调用似乎没有任何效果。实际上,没有记录。
这种行为记录在哪里?我真的不明白。
答案 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)
是
您已要求记录某些内容。因此,日志记录必须构建默认配置。一旦配置了日志......好吧......它已经配置好了。
“配置了记录器对象, 以下方法创建日志 提示:“
此外,您可以阅读有关创建处理程序以防止虚假日志记录的信息。但对于糟糕的实施而言,这不仅仅是一种有用的技术。
这是一个诀窍。
除了logging.getlogger()
请求之外,任何模块都无法执行任何操作。
只有if __name__ == "__main__":
才能进行日志记录配置。
如果您在模块中进行全局级别的日志记录,则可以强制日志记录来构建它的默认配置。
不要在任何模块中全局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()