用于非平凡用途的Python日志记录?

时间:2009-10-16 23:04:29

标签: python logging

我正在尝试使用python日志记录模块来执行复杂的操作。我将把这个设计的动机留下来,因为它会大大延长帖子,但是我需要一个root logger来为我们的代码和使用日志记录的库发送一个常规日志文件 - 以及一系列其他记录器不同的日志文件。

整体设置应如下所示。在这个例子中,我将尽一切努力来简化代码。


import logging, sys
root = logging.getLogger('')
top = logging.getLogger('top')
bottom = logging.getLogger('top.bottom')

class KillFilter(object):
    def filter(self, msg):
        return 0

root_handler = logging.StreamHandler(sys.stdout)
top_handler = logging.StreamHandler(sys.stdout)
bottom_handler = logging.StreamHandler(sys.stdout)
root_handler.setFormatter(logging.Formatter('ROOT'))
top_handler.setFormatter(logging.Formatter('TOP HANDLER'))
bottom_handler.setFormatter(logging.Formatter("BOTTOM HANDLER"))

msg_killer = KillFilter()

root.addHandler(root_handler)
top.addHandler(top_handler)
bottom.addHandler(bottom_handler)

top.addFilter(msg_killer)

root.error('hi')
top.error('hi')
bottom.error('hi')

此输出


ROOT
BOTTOM HANDLER
ROOT

第二个根处理程序调用不应该是因为根据日志记录文档,msg_killer将阻止消息进入根记录器。显然,文档可以使用改进。

编辑:删除了我的“当下”用于python日志记录的严厉措辞。

2 个答案:

答案 0 :(得分:7)

首先,我在我的机器上运行不同的输出(运行Python 2.6):

ROOT
BOTTOM HANDLER
TOP HANDLER
ROOT

过滤仅应用于发出消息的记录器,如果它通过过滤器,则它会传播到父记录器的所有处理程序(而不是记录器本身) - 我不知道其基本原理这个决定。如果要在“顶部”Logger实例中停止传播,请设置:

top.propagation = False

答案 1 :(得分:1)

来源与不同的案例标识符混淆,更有用的版本:

import logging, sys
root = logging.getLogger('')
level1 = logging.getLogger('level1')
level2 = logging.getLogger('level1.level2')

class KillFilter(object):
    def filter(self, msg):
        return 0

root_handler = logging.StreamHandler(sys.stdout)
top_handler = logging.StreamHandler(sys.stdout)
bottom_handler = logging.StreamHandler(sys.stdout)
root_handler.setFormatter(logging.Formatter('ROOT HANDLER - %(msg)s'))
top_handler.setFormatter(logging.Formatter('level1 HANDLER - %(msg)s'))
bottom_handler.setFormatter(logging.Formatter('level2 HANDLER - %(msg)s'))

msg_killer = KillFilter()

root.addHandler(root_handler)
level1.addHandler(top_handler)
level2.addHandler(bottom_handler)

level1.addFilter(msg_killer)
level1.propagate = False

root.error('root_message')
level1.error('level1_message')
level2.error('level2_message')