我有多个模块使用相同的utils.py包。如何使记录器utils.py不同而不必从调用者(即 ClassA 或 ClassB)传递记录器变量?
非常简单的示例代码如下。实际上,我在 中有很多函数和类utils.py,这就是为什么我不想将logger变量传递到utils.py.
~/test-two-loggers$ tree .
??? main.py
??? configs.py
??? ClassA.py
??? ClassB.py
??? utils.py
0 directories, 5 files
Run Code Online (Sandbox Code Playgroud)
主文件
import ClassA
import ClassB
ClassA.func()
ClassB.func()
Run Code Online (Sandbox Code Playgroud)
类A.py
import utils
import configs
import logging
def func():
logger = logging.getLogger("classA")
logger.info("in ClassA")
utils.common_func(logger) # I want to change this line!!!!
Run Code Online (Sandbox Code Playgroud)
类B.py
import utils
import configs
import logging
def func():
logger = logging.getLogger("classB")
logger.info("in ClassB")
utils.common_func(logger) # I want to change this line!!!!
Run Code Online (Sandbox Code Playgroud)
实用程序.py
def common_func(logger): # I want to change this line!!!!
# do a lot of things ClassA and ClassB both need to do
logger.info("in utils - step one finished")
# do a lot of things ClassA and ClassB both need to do
logger.info("in utils - step two finished")
# do a lot of things ClassA and ClassB both need to do
logger.info("in utils - step three finished")
Run Code Online (Sandbox Code Playgroud)
配置文件
import logging.config
logging_config = {
"version": 1,
"formatters": {
"formatter_a": {
"format": u"[A][%(levelname)s] %(module)s.%(lineno)d: %(message)s"
},
"formatter_b": {
"format": u"[B][%(levelname)s] %(module)s.%(lineno)d: %(message)s"
},
},
"handlers": {
"console_a": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "formatter_a",
"stream": "ext://sys.stdout"
},
"console_b": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "formatter_b",
"stream": "ext://sys.stdout"
},
},
"loggers": {
"classA": {
"level": "DEBUG",
"handlers": ["console_a"],
"propagate": "no"
},
"classB": {
"level": "DEBUG",
"handlers": ["console_b"],
"propagate": "no"
},
},
}
logging.config.dictConfig(logging_config)
Run Code Online (Sandbox Code Playgroud)
我想要的结果:
~/test-two-loggers$ python main.py
[A][INFO] ClassA.7: in ClassA
[A][INFO] utils.3: in utils - step one finished
[A][INFO] utils.5: in utils - step two finished
[A][INFO] utils.7: in utils - step three finished
[B][INFO] ClassB.7: in ClassB
[B][INFO] utils.3: in utils - step one finished
[B][INFO] utils.5: in utils - step two finished
[B][INFO] utils.7: in utils - step three finished
Run Code Online (Sandbox Code Playgroud)
但我想要除此之外的另一种解决方案。我不想将logger变量传递给utils.
Gus*_*rra -1
您可以更改格式化程序并使用extra关键字参数将额外的字典参数传递给日志消息。这允许您传递任何您想要假装正在调用记录器的“模块”。
因此,将您的格式化程序更改为:
"[A][%(levelname)s] %(module)s.%(lineno)d: %(message)s"
Run Code Online (Sandbox Code Playgroud)
到:
"[A][%(levelname)s] %(mymodule)s.%(lineno)d: %(message)s"
Run Code Online (Sandbox Code Playgroud)
并将您的函数称为:
logger.info("in utils", extra={'mymodule':'somemodule'})
Run Code Online (Sandbox Code Playgroud)
如果您想使用正在调用的真实'somemodule'模块,请更改为__name__.
我也虽然可能只是覆盖module(所以你必须更改你的格式化程序)的值,但logging不允许这样做,所以看来你必须更改你的格式化程序。
编辑:
为了更加清楚,您的func()inClassA.py应该更改为:
def func():
logger = logging.getLogger("classA")
logger.info("in ClassA", extra={'mymodule':__name__)
logger.info("in utils", extra={'mymodule':'utils')
utils.common_func() #call the function without passing the logger
Run Code Online (Sandbox Code Playgroud)
在你的字典中,你应该logging_config将字符串更改module为.logging_config['formatters']['formatter_a']['format']mymodule
对于B类也同样如此。显然你应该删除common_funcusing的行logger。
进一步参考:
extra。)