繁体   English   中英

如何避免从 Python 中的自定义记录器调用根处理程序?

[英]How to avoid root handler being called from the custom logger in Python?

我有一个具有调试级别的日志记录模块的基本配置 - 现在我只想创建另一个具有错误级别的记录器。 我怎样才能做到这一点?

问题是除了错误处理程序之外还调用了根处理程序 - 这是我想要避免的事情。

import logging
fmt = '%(asctime)s:%(funcName)s:%(lineno)d:%(levelname)s:%(name)s:%(message)s'
logging.basicConfig(level=logging.DEBUG, format=fmt)

logger = logging.getLogger('Temp')
logger.setLevel(logging.ERROR)
handler = logging.StreamHandler()
handler.setLevel(logging.ERROR)
logger.addHandler(handler)

logger.error('boo')

上面的代码打印了两次 boo,而我只期望一次,我不知道如何处理这个烦人的问题......

In [4]: logger.error('boo')
boo
2021-04-26 18:54:24,329:<module>:1:ERROR:Temp:boo

In [5]: logger.handlers
Out[5]: [<StreamHandler stderr (ERROR)>]

关于日志记录模块的一些基础知识

  • logger:接收日志字符串的人,按预定义的级别对其进行排序,然后使用他自己的处理程序(如果有)来处理日志,并且默认情况下将日志传递给他的上级。
  • root logger:上级中的上级,做普通 logger 所做的所有事情,但不会将收到的日志传递给其他任何人。
  • handler :记录器的私人承包商,他实际上对日志做任何事情,例如。 格式化日志,将其写入文件或stdout ,或通过 tcp/udp 发送。
  • formatter :主题, handler应用于日志的设计。
  • basicConfig :配置root记录器的快捷方式。 当您希望他完成所有工作并且他的所有较低级别的伐木工只会将日志传递给他时,这很有用。
    在没有参数的情况下, basicConfigroot记录器的级别设置为WARNING并将 output 日志添加到stderrStreamHandler

你做了什么

  1. 您创建了一种format并使用快捷方式basicConfig来配置root记录器。 您希望根记录器执行所有实际的记录操作
  2. 您创建了一个新的低等级记录器Temp
  3. 您希望它只接受ERROR级别及以上的日志。
  4. 您创建了另一个StreamHandler 其中 output 默认为stdout
  5. 您希望它只处理ERROR级别及以上
  6. 哦,你把它分配给了Temp记录器,这使得5.多余,因为级别设置为3.
    哦等等,以为你只是想让root记录器从1.开始就完成这项工作。!
  7. 您使用记录器记录了一个ERROR

发生了什么

您的Temp记录器接受了ERROR级别的字符串boo 然后告诉它的处理程序处理字符串。 由于该处理程序没有分配任何formatter ,因此它按原样将字符串输出到stdoutboo
之后, Temp记录器将字符串boo传递给他的上级,即root记录器。

由于日志级别为ERROR > WARNING ,因此root记录器接受了日志。 然后root记录器告诉其处理程序处理字符串boo 此处理程序将格式字符串应用于boo 添加时间戳,添加位置,添加通过日志的记录器的名称等。
最后将结果输出到stderr2021-04-26 18:54:24,329:<module>:1:ERROR:Temp:boo

改正它

由于您的代码完全按照您的要求执行,因此您必须尽可能详细地告诉它。

  • 只有在你懒惰的时候才使用basicConfig 通过删除basicConfig行,您的问题解决了。
  • 使用logger = logging.getLogger('__name__')以便记录器具有模块的名称。 查看日志并确切知道它来自哪个import path
  • 决定一个记录器是应该为它自己保留日志还是通过propagate属性将它传递到链上。 在您的情况下, logger.propagate = False也可以解决问题。
  • 使用dictConfig文件,这样您就不会弄乱配置代码。
  • 在实践中,您不应该将处理程序添加到您的记录器,而只是让记录器将日志一直传递给root并让根执行实际的日志记录。 为什么?
    • 其他人将您的代码用作模块,可以控制日志记录。 例如,不是 output 到 stdout 而是到 tcp/udp,output 具有不同的格式等。
    • 您可以通过propagating=False完全关闭特定记录器的日志记录。
    • 如果您只将它们添加到root记录器,您就可以准确地知道代码中的所有处理程序和格式化程序。 您可以集中控制日志记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM