这个自定义日志记录器为什么不使用根格式化程序?

huangapple go评论69阅读模式
英文:

Why doesn't this custom logger use the root formatter?

问题

以下是您要翻译的内容:

我理解的日志记录文档方式是,对于那些没有配置处理程序的记录器的所有调用最终都会“传递”到根记录器(并隐式地使用其格式化程序)。

在下面的示例中,"log" 和 "mylog" 都不是根记录器。然而,对 log.error() 的调用使用了根记录器的格式,但 mylog.error() 并没有。这是为什么呢?

import logging

class MyLogger(logging.getLoggerClass()):
    pass

mylog = MyLogger("mytest")
log = logging.getLogger("test")
root = logging.getLogger()

h = logging.StreamHandler()
f = logging.Formatter(fmt="[%(levelname)s] %(message)s")
h.setFormatter(f)
root.addHandler(h)

log.error("Normal log")
mylog.error("Test log")

输出:

[ERROR] Normal log
Test log

(背景信息:我编写了一个自定义记录器,它需要额外的对象参数并增强消息中的关于该对象的信息。对该自定义记录器的调用散布在多个模块中,与使用 logging.getLogger() 获取的记录器并存。当然,我希望这些自定义日志也使用我集中设置的相同处理程序和格式化程序。)

英文:

The way I understand the logging documentation is that all calls to loggers that don't have handlers configured on them will eventually "fall through" to the root logger (and implicitly also use its formatter).

In the example below, neither "log" nor "mylog" are the root logger. Yet the call to log.error() uses the root logger's format, but mylog.error() doesn't. Why is that?

import logging

class MyLogger(logging.getLoggerClass()):
    pass

mylog = MyLogger("mytest")
log = logging.getLogger("test")
root = logging.getLogger()

h = logging.StreamHandler()
f = logging.Formatter(fmt="[%(levelname)s] %(message)s")
h.setFormatter(f)
root.addHandler(h)

log.error("Normal log")
mylog.error("Test log")

Output:

[ERROR] Normal log
Test log

(Background: I've written a custom logger that takes an extra object argument and augments the message with info about that object. Calls to that custom logger are sprinkled throughout several modules, alongside loggers acquired with logging.getLogger(). Of course I want those custom logs to use the same handlers and formatters I've set up centrally.)

答案1

得分: 1

From the documentation:

> 请注意,Logger 不应该直接实例化,而应始终通过模块级别的函数 logging.getLogger(name) 来创建。

不要通过调用 MyLogger 来实例化 mylog,而是使用 logging.setLoggerClass 来设置由 getLogger 创建 mylog 时使用的类。此外,使用 logging.basicConfig 来配置日志系统。

import logging

logging.basicConfig(format="[%(levelname)s] %(message)s")

class MyLogger(logging.getLoggerClass()):
    pass

root = logging.getLogger()
log = logging.getLogger("test")
logging.setLoggerClass(MyLogger)
mylog = logging.getLogger("mytest")

log.error("Normal log")
mylog.error("Test log")
英文:

From the documentation:

> Note that Loggers should NEVER be instantiated directly, but always through the module-level function logging.getLogger(name).

Instead of instantiating mylog by calling MyLogger, use logging.setLoggerClass to set the class used by getLogger to create mylog. Also, use logging.basicConfig to configure the logging system.

import logging

logging.basicConfig(format="[%(levelname)s] %(message)s")


class MyLogger(logging.getLoggerClass()):
    pass


root = logging.getLogger()
log = logging.getLogger("test")    
logging.setLoggerClass(MyLogger)
mylog = logging.getLogger("mytest")

log.error("Normal log")
mylog.error("Test log")

答案2

得分: 0

感谢chetner的建议,我找到了一个简单的解决方法。我添加了这个:

root = logging.getLogger()
for h in root.handlers:
    mylog.addHandler(h)

至少在我的测试案例中有效。

英文:

Thanks to chetner's tip I came to a simple solution. I added this:

root = logging.getLogger()
for h in root.handlers:
    mylog.addHandler(h)

It works at least in my test case.

huangapple
  • 本文由 发表于 2023年4月20日 03:59:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76058384.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定