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

标签 python logging

我具有调试级别的日志记录模块的基本配置-现在我只想创建另一个具有错误级别的记录器。我怎样才能做到这一点?
问题是除了错误处理程序之外,还调用了根处理程序-这是我要避免的事情。

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)>]

最佳答案

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

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

  • 你做了什么
  • 您创建了一个format,并使用了一个快捷方式basicConfig来配置root记录器。您希望root logger进行所有实际的日志记录操作
  • 您创建了一个新的低级记录器Temp
  • 您希望它仅接受ERROR级及更高级别的日志。
  • 您创建了另一个StreamHandler。默认情况下,哪个输出为stdout
  • 您希望它仅处理ERROR级别以及
  • 以上
  • 哦,您已将其分配给Temp记录器,由于在5.中设置了级别,这使3.成为多余的
    哦,等等,以为自root以来,您只希望1.记录器执行此工作!
  • 您使用记录器记录了一个ERROR

  • 发生了什么
    您的Temp记录器在boo级别接受了字符串ERROR。然后告诉它的处理程序来处理字符串。由于此处理程序未分配任何formatter,因此将字符串原样输出到stdout:boo之后,Temp记录器将字符串boo传递给他的上级root记录器。root记录器接受了日志,因为日志级别为ERROR> WARNING
    然后,root记录器告诉其处理程序处理字符串boo
    该处理程序将格式字符串应用于boo。添加时间戳,添加位置,添加通过日志的记录器的名称,等等。
    最后,将结果输出到stderr:2021-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,并让根进行实际的记录。为什么?
  • 其他人将您的代码用作模块,可以控制日志记录。例如,不输出到stdout,而是输出到tcp/udp,以其他格式输出,等等。
  • 您可以通过propagating=False完全关闭来自特定记录器的日志记录。
  • 如果仅将它们添加到root记录器,则您将完全了解代码中的所有处理程序和格式化程序。您可以对日志进行集中控制。

  • 关于python - 如何避免在Python的自定义记录器中调用根处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67269916/

    相关文章:

    python - 在 Python 中使用相同比较运算符的倍数压缩 if 语句

    python - 如何在 python 中使用 wnck 将 gtk 窗口从一个工作区移动到另一个工作区?

    java - Websphere MQ - Java 应用程序 - 启用日志记录

    java - Logback:如何将日志目录从 "tomcat/bin"更改为与应用程序相关?

    python - 使用修饰函数作为函数的默认参数

    python - 查看 Python (Django) 中的当前日志记录配置

    python - 在 Mac 中导入自己的 Python 模块

    Python排序问题 - 给定 ['url' , 'tag1' , 'tag2' ,..] 列表和搜索规范 ['tag3' , 'tag1' ,...],返回相关 url 列表

    java - 获取 Log4j2 错误

    python - 在 Numpy 中向量化 for 循环