运行 logging.basicConfig 之前的 Python 日志记录?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1943747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python logging before you run logging.basicConfig?
提问by Joseph Turian
It appears that if you invoke logging.info() BEFOREyou run logging.basicConfig, the logging.basicConfig call doesn't have any effect. In fact, no logging occurs.
看来,如果您在运行 logging.basicConfig之前调用 logging.info() ,则 logging.basicConfig 调用没有任何效果。事实上,不会发生日志记录。
Where is this behavior documented? I don't really understand.
这种行为记录在哪里?我真的不明白。
回答by Carlos A. Ibarra
You can remove the default handlers and reconfigure logging like this:
您可以删除默认处理程序并重新配置日志记录,如下所示:
# 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)
回答by S.Lott
Yes.
是的。
You've asked to log something. Logging must, therefore, fabricate a default configuration. Once logging is configured... well... it's configured.
你要求记录一些东西。因此,日志记录必须制作默认配置。一旦配置了日志记录......好吧......它已经配置好了。
"With the logger object configured, the following methods create log messages:"
“配置记录器对象后,以下方法会创建日志消息:”
Further, you can read about creating handlers to prevent spurious logging. But that's more a hack for bad implementation than a useful technique.
此外,您可以阅读有关创建处理程序以防止虚假日志记录的信息。但这与其说是一种有用的技术,不如说是对糟糕实现的一种黑客攻击。
There's a trick to this.
这有一个技巧。
No module can do anything except
logging.getlogger()
requests at a global level.Only the
if __name__ == "__main__":
can do a logging configuration.
除了
logging.getlogger()
全局级别的请求之外,没有任何模块可以做任何事情。只有
if __name__ == "__main__":
可以进行日志记录配置。
If you do logging at a global level in a module, then you may force logging to fabricate it's default configuration.
如果您在模块中进行全局级别的日志记录,那么您可以强制日志记录来制作它的默认配置。
Don't do logging.info
globally in any module. If you absolutely think that you must have logging.info
at a global level in a module, then you have to configure logging beforedoing imports. This leads to unpleasant-looking scripts.
不要logging.info
在任何模块中进行全局操作。如果您绝对认为您必须logging.info
在一个模块中具有全局级别,那么您必须在执行导入之前配置日志记录。这会导致令人不快的脚本。
回答by Paul Kremer
This answer from Carlos A. Ibarra is in principle right, however that implementation might break since you are iterating over a list that might be changed by calling removeHandler(). This is unsafe. Two alternatives are:
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)
or:
或者:
logging.root.handlers = []
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)
where the first of these two using the loop is the safest (since any destruction code for the handler can be called explicitly inside the logging framework). Still, this is a hack, since we rely on logging.root.handlers to be a list.
其中使用循环的这两个中的第一个是最安全的(因为可以在日志记录框架内显式调用处理程序的任何销毁代码)。尽管如此,这是一个黑客,因为我们依赖 logging.root.handlers 作为一个列表。
回答by Dan H
Here's the one piece of the puzzle that the above answers didn't mention... and then it will all make sense: the "root" logger -- which is used if you call, say, logging.info() before logging.basicConfig(level=logging.DEBUG) -- has a default logging level of WARNING.
这是上面的答案没有提到的一个难题……然后一切都有意义了:“根”记录器——如果你在登录之前调用,比如,logging.info(),就会使用它。 basicConfig(level=logging.DEBUG) --有一个默认的日志级别 WARNING。
That's why logging.info() and logging.debug() don't do anything: because you've configured them not to, by... um... not configuring them.
这就是为什么 logging.info() 和 logging.debug() 不做任何事情:因为你已经将它们配置为not,通过...... 嗯......没有配置它们。
Possibly related (this one bit me): when NOT calling basicConfig, I didn't seem to be getting my debug messages, even though I set my handlers to DEBUG level. After a bit of hair-pulling, I found you have to set the level of the custom loggerto be DEBUG as well. If your logger is set to WARNING, then setting a handler to DEBUG (by itself) won't get you any output on logger.info() and logger.debug().
可能相关(这有点我):当不调用 basicConfig 时,我似乎没有收到调试消息,即使我将处理程序设置为调试级别。经过一番折腾,我发现您还必须将自定义记录器的级别设置为 DEBUG。如果您的记录器设置为 WARNING,那么将处理程序设置为 DEBUG(本身)不会让您在 logger.info() 和 logger.debug() 上获得任何输出。
回答by corford
A cleaner version of the answer given by @paul-kremer is:
@paul-kremer 给出的答案的更清晰版本是:
while len(logging.root.handlers):
logging.root.removeHandler(logging.root.handlers[-1])
Note: it is generally safe to assume logging.root.handlers will always be a list (see: https://github.com/python/cpython/blob/cebe9ee988837b292f2c571e194ed11e7cd4abbb/Lib/logging/init.py#L1253)
注:它一般是安全的假设logging.root.handlers将永远是一个列表(参见:https://github.com/python/cpython/blob/cebe9ee988837b292f2c571e194ed11e7cd4abbb/Lib/logging/初始化的.py#L1253)