Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何避免在Python中从自定义记录器调用根处理程序?_Python_Logging - Fatal编程技术网

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

如何避免在Python中从自定义记录器调用根处理程序?,python,logging,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('

我有一个调试级别日志模块的基本配置-现在我只想创建另一个错误级别日志。我该怎么做

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

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)>]
[4]中的
:logger.error('boo')
喝倒采
2021-04-26 18:54:24329::1:错误:温度:boo
在[5]中:logger.handlers
输出[5]:[]
有关日志记录模块的一些基础知识
  • 记录器:接收日志字符串,按预定义级别对其进行排序,然后使用自己的处理程序(如果有)处理日志的人员,默认情况下,将日志传递给其上级
  • root
    logger:上级中的上级,完成普通记录器所做的所有事情,但不会将收到的日志传递给任何其他人
  • handler
    :记录器的私人承包商,实际对日志执行任何操作,例如格式化日志、将其写入文件或
    stdout
    ,或通过tcp/udp发送日志
  • 格式化程序
    :主题,
    处理程序
    应用于日志的设计
  • basicConfig
    :配置
    root
    记录器的快捷方式。当您希望他完成所有工作,而所有级别较低的伐木工人只需将日志传递给他时,此功能非常有用。
    在没有参数的情况下,
    basicConfig
    root
    记录器的级别设置为
    WARNING
    ,并添加一个
    StreamHandler
    ,将日志输出到
    stderr
你做了什么
  • 您创建了一个
    格式
    ,并使用快捷方式
    basicConfig
    配置
    root
    记录器。您希望根记录器完成所有实际的日志记录工作
  • 您创建了一个新的低阶记录器
    Temp
  • 您希望它只接受
    错误
    级别及以上的日志
  • 您创建了另一个
    StreamHandler
    。默认情况下,输出到标准输出
  • 您希望它只处理
    错误
    级别及以上
  • 哦,您将其分配给了
    Temp
    记录器,这使得
    5.
    冗余,因为级别在
    3中设置。

    哦,等等,我以为你只是想让
    根用户
    记录器来做这项工作,因为
    1。
  • 您使用记录器记录了一个
    错误
  • 怎么搞的? 您的
    Temp
    记录器在
    ERROR
    级别接受了字符串
    boo
    。然后让其处理程序处理该字符串。由于此处理程序没有分配任何
    格式化程序
    ,因此它将字符串按原样输出到
    stdout
    boo

    之后,
    Temp
    logger将字符串
    boo
    传递给他的上级
    root
    记录器

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

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

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

    感谢您的详细回答。