Python日志模块允许用户以分层方式创建记录器。虽然在高层次上理解它,但是当我的代码分布在多个类中,并且实际的函数流将创建一个复杂的网格时,我很难实现这样的层次结构。。在
我可以用下面的代码做一个简单的层次结构:
import logging
logFormatter = logging.Formatter("%(asctime)s [%(levelname)-5.5s] %(childname)s %(message)s")
rootLogger = logging.getLogger()
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)
rootLogger.setLevel(logging.INFO)
rootLogger.info("Hi..",extra={'childname':' '})
cL1= rootLogger.getChild("Child1")
cL1.info("Hello..",extra={'childname': cL1.name})
cL2 = cL1.getChild('Child2')
cL2.info("Hi .. hello..",extra={'childname':cL2.name})
上述代码块的输出将是
^{pr2}$因此,我有了额外的参数,我可以在日志中转储整个层次结构。在
现在,当代码在多个类、多个文件中拆分时,如何实现这一点呢?在
moduleA.py
class A:
def __init__(self,name):
self.name=name
def doSomethingForA_1(self,**kwargs):
self.logger(msg="Yes i did A_1",level=logging.INFO)
def doSomethingForA_2(self,**kwargs):
self.logger(msg="Yes i did A_2",level=logging.INFO)
def logger(msg,level):
'''How do i get the parent logger to create the child logger here?'''
logger=parentLogger.getLogger(self.name)
logger.log(msg,level,extra={'childname':self.name})
moduleAggregationType1.py
class AggregatorType1:
def __init__(self,name):
self.name=name
self.objs = []
def doAggregationType1(self,**kwargs):
self.logger(msg="Starting aggregation Operation-1",level=logging.INFO)
for obj in self.objs:
obj.doSomethingForA_1()
def logger(msg,level):
'''How do i get the parent logger to create the child logger here?'''
logger=parentLogger.getLogger(self.name)
logger.log(msg,level,extra={'childname':self.name})
moduleAggregationType2.py
class AggregatorType2:
def __init__(self,name):
self.name=name
self.objs = []
def doAggregationType2(self,**kwargs):
self.logger(msg="Starting aggregation Operation-2",level=logging.INFO)
for obj in self.objs:
obj.doSomethingForA_2()
def logger(msg,level):
'''How do i get the parent logger to create the child logger here?'''
logger=parentLogger.getLogger(self.name)
logger.log(msg,level,extra={'childname':self.name})
对于这些模块,假设我通过导入它们来编写脚本。在
agg_1 = AggregatorType1(name='agg_1')
agg_1.objs = [A(name='aType1_1'),A(name='aType1_2'),A(name='aType1_3')]
agg_2 = AggregatorType1(name='agg_1')
agg_2.objs = [A(name='aType2_1'),A(name='aType2_2'),A(name='aType2_3')]
在这种情况下,我的日志应该是:
2017-08-23 22:52:47,999 [INFO ] agg_1 Starting aggregation Operation-1
2017-08-23 22:52:47,999 [INFO ] agg_1.aType1_1 Yes i did A_1
2017-08-23 22:52:47,999 [INFO ] agg_1.aType1_2 Yes i did A_1
2017-08-23 22:52:47,999 [INFO ] agg_1.aType1_3 Yes i did A_1
2017-08-23 22:52:47,999 [INFO ] agg_2 Starting aggregation Operation-2
2017-08-23 22:52:47,999 [INFO ] agg_2.aType2_1 Yes i did A_2
2017-08-23 22:52:47,999 [INFO ] agg_2.aType2_2 Yes i did A_2
2017-08-23 22:52:47,999 [INFO ] agg_2.aType2_3 Yes i did A_2
因此,在执行每个方法时,我应该确定我的日志应该传播到的父记录器是什么。。在
现在我们可以为所有可调用的方法创建一个decorator,我们可以确定其中的父logger,并创建一个子logger并在decorator的末尾删除它。但问题仍然存在。。在
如何在运行时在每个方法级别确定父记录器?在
简单的回答你不能。没有所谓的“家长日志”。python日志系统承诺的是,您可以在解释器进程的任何地方通过名称引用同一个记录器。在
所以你的选择是(在我看来):
1)要么静态声明在构造变量时要记录的位置(这很难看而且容易出错)
2)使用内置的
%(module)s
和%(funcName)s
修饰符。为此,您必须停止使用您自己的logger
方法,因为它将屏蔽您所在方法的实际名称3)使用
traceback
模块在运行时获取堆栈跟踪我修改了一点代码以反映所有这些更改(并在途中删除了可选参数)
主要内容:
^{pr2}$这将提供以下输出:
相关问题 更多 >
编程相关推荐