首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在python中创建分层记录器

在python中创建分层记录器
EN

Stack Overflow用户
提问于 2017-08-24 01:51:44
回答 1查看 533关注 0票数 1

Python日志记录模块允许用户以分层方式创建日志记录器。虽然在高层次上理解它,但当我的代码分布在多个类中,并且实际的函数流将创建一个复杂的网格时,我很难实现这样的层次结构。

我可以用下面的代码做一个简单的层次结构:

代码语言:javascript
复制
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})

上述代码块的输出将为

代码语言:javascript
复制
In [8]: rootLogger.info("Hi..",extra={'childname':' '})
2017-08-23 22:52:47,703 [INFO ]    Hi..

In [10]: cL1.info("Hello..",extra={'childname': cL1.name})
2017-08-23 22:52:47,999 [INFO ] Child1  Hello..

In [12]: cL2.info("Hi .. hello..",extra={'childname':cL2.name})
2017-08-23 22:52:48,296 [INFO ] Child1.Child2  Hi .. hello..

因此,有了这个额外的参数,我就能够在日志中转储整个层次结构。

现在,当代码跨多个类、跨多个文件拆分时,如何实现这一点?

代码语言:javascript
复制
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})

使用这些模块,假设我通过导入它们来编写脚本。

代码语言:javascript
复制
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')]

在这种情况下,我的日志记录应该是:

代码语言:javascript
复制
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

因此,在执行每个方法时,我应该确定我的日志应该传播到的父记录器是什么。

现在我们可以为所有可调用的方法创建一个装饰器,我们可以在其中确定父记录器,并创建子记录器并在装饰器的末尾删除它。但问题仍然存在..

如何在每个方法级别确定运行时的父记录器?

EN

回答 1

Stack Overflow用户

发布于 2017-08-24 05:24:32

简单的答案是你不能。没有“家长记录器”这回事。python日志记录系统承诺的是,您可以在解释器进程中的任何位置通过名称引用相同的日志记录器。

所以你的选择是(在我看来):

1)要么在构造变量时静态声明日志位置(这很难看,而且容易出错)

2)使用内置的%(module)s%(funcName)s修饰符。为此,您将不得不停止使用您自己的logger方法,因为它将屏蔽您所在方法的实际名称

3)使用traceback模块在运行时获取堆栈跟踪

我对您的代码进行了一些修改以反映所有这些更改(并在此过程中删除了您的可选参数)

代码语言:javascript
复制
class A():
    def __init__(self, name):
        logger = logging.getLogger(name)
        self.log = logger.log
    def doSomethingForA_1(self,**kwargs):
        self.log(msg="Yes i did A_1",level=logging.INFO)
    def doSomethingForA_2(self,**kwargs):
        stack = traceback.extract_stack(limit=2)
        self.log(msg='Caller=%s:%d>%s>'%(stack[0][0:3]), level=logging.INFO)

在main中:

代码语言:javascript
复制
logFormatter = logging.Formatter("[%(levelname)s] %(name)s <%(module)s.%(funcName)s>  %(message)s")


agg_1 = AggregatorType1(name='agg_1')
agg_2 = AggregatorType2(name='agg_2')

agg_1.objs = [A(name='agg_1.aType1_1'),A(name='agg_1.aType1_2'),A(name='agg_1.aType1_3')]
agg_2.objs = [A(name='agg_2.aType2_1'),A(name='agg_2.aType2_2')]

agg_1.doAggregationType1()
agg_2.doAggregationType2()

这将提供以下输出:

代码语言:javascript
复制
[INFO] root <main.<module>>  Hi..
[INFO] agg_1 <moduleAggregationType1.doAggregationType1>  Starting aggregation Operation-1
[INFO] agg_1.aType1_1 <moduleA.doSomethingForA_1>  Yes i did A_1
[INFO] agg_1.aType1_2 <moduleA.doSomethingForA_1>  Yes i did A_1
[INFO] agg_1.aType1_3 <moduleA.doSomethingForA_1>  Yes i did A_1
[INFO] agg_2 <moduleAggregationType2.logger>  Starting aggregation Operation-2
[INFO] agg_2.aType2_1 <moduleA.doSomethingForA_2>  Caller=<moduleAggregationType2.py:11.doAggregationType2>
[INFO] agg_2.aType2_2 <moduleA.doSomethingForA_2>  Caller=<moduleAggregationType2.py:11.doAggregationType2>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45846387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档