Ng *_*-Ee 5 python logging kivy
我已经看到在多个模块中使用 Python 日志记录和类似的推荐使用:-
import logging
logger = logging.getLogger(__name__)
Run Code Online (Sandbox Code Playgroud)
在每个模块中。但是我也使用 Kivy 作为前端,它有自己的日志代码。总而言之,Kivy 的日志代码将 logging.root 设置为它自己的类。
这对我来说意味着 Kivy 分配的处理程序不会被我的子模块继承。
我该如何解决这个问题?我什至尝试过手动分配处理程序如下:-
logging.getLogger(my.module.name).addHandler(handler)
Run Code Online (Sandbox Code Playgroud)
它似乎仍然没有出现在我的控制台日志中。显然,我也不希望每个模块都执行上述操作。
编辑
澄清一下,我想将 Kivy 应用程序设置为能够处理使用“推荐”日志方法的模块,而无需对模块代码进行任何更改。
为什么不使用logging.Logger.getChild?特别是,在您的模块中,调用
mylogger = logging.getLogger().getChild(__name__)
Run Code Online (Sandbox Code Playgroud)
如果在导入模块之后再导入模块kivy.logger,则根记录器的名称将为kivy,因此mylogger的名称将为kivy.module.name,更重要的是,它将把其消息传播到根记录器kivy。另一方面,如果kivy.logger尚未导入,mylogger则 的名称将只是module.name,因此默认情况下不附加任何处理程序。
例子:
test.py:
import logging
class MyClass(object):
def __init__(self):
super(MyClass, self).__init__()
self.logger = logging.getLogger().getChild(__name__)
self.value = 0
def act(self):
self.value += .5
self.logger.warning("MyClass.act: value: {}".format(self.value))
if __name__ == '__main__':
mc = MyClass()
mc.act()
mc.act()
mc.act()
Run Code Online (Sandbox Code Playgroud)
和app.py:
from kivy.app import App
from kivy.logger import Logger
from kivy.clock import Clock
from kivy.properties import ObjectProperty, NumericProperty
from kivy.uix.widget import Widget
from test import MyClass
class AnApp(App):
mc = ObjectProperty()
value = NumericProperty(0)
def action_c(self, dt=0):
self.value += 1
self.mc.act()
Logger.info("action_c: value now {}".format(self.value))
def build(self):
self.mc = MyClass()
Clock.schedule_interval(self.action_c, 1)
return Widget()
AnApp().run()
Run Code Online (Sandbox Code Playgroud)
和app_wo_kivy.py:
import logging
from test import MyClass
logging.getLogger().addHandler(logging.StreamHandler())
mc = MyClass()
mc.act()
mc.act()
Run Code Online (Sandbox Code Playgroud)
另一种方法:在 kivy 应用程序中,将其放在第一位:
from kivy.logger import Logger
import logging
logging.Logger.manager.root = Logger # before importing modules using logging
Run Code Online (Sandbox Code Playgroud)
有了这个,您应该能够使用获取记录器的标准方法(logger = logging.getLogger(__name__))。这适用于现有模块(假设它们不会弄乱logging自己......)。logging.Logger.manager保存记录器字典并确定层次结构。每当使用 创建新记录器 时logging.getLogger,logging.Manager._fixupParents都会调用 ,当找不到其他父记录器时,它将指定logging.Logger.manager.root 为父记录器。如果没有上面的行,这仍然是原始的根记录器,因此将使用它。
现在我不知道这是否会产生意想不到的后果;但至少记录器名称解析不应受到损害,因为根记录器的名称永远不会被检查。