我想让python日志输出以对应于记录树的树的形式.看看例子.
让我们说我们有一个代码:
import logging
logger_a = logging.getLogger("a")
logger_a_b = logging.getLogger("a.b")
logger_a_b_c = logging.getLogger("a.b.c")
# ...
logger_a.debug("One")
logger_a_b.warning("two")
logger_a_b.warning("three")
logger_a_b_c.critical("Four")
logger_a_b.warning("Five")
输出应该是这样的:
<--"a"
| DEBUG: One
|
o<--"a.b"
| | WARNING: Two
| | WARNING: Three
| |
| o<--"a.b.c"
| | CRITICAL: Four
| |
| | WARNING: Five
我可以手动为每个日志编写格式化程序,但它没有解决插入类似o< - “a.b”的问题,我宁愿通过日志记录结构自动计算偏移量. 有一个名为logging tree的模块.它打印日志记录布局.我想要的是以大致相同的方式打印日志消息.
你知道任何图书馆,方法吗?
最佳答案
根据您的示例,我创建了一个自定义Formatter来处理树.
import logging
# custom tree formatter
class TreeFormatter(logging.Formatter):
formatPrefix = {} # map loggername,formatPrefix
def format(self,record):
s = ""
# first time this name is encountered: create the prefix and print the name
if not record.name in self.formatPrefix:
f = self.getFormatPrefix(record)
s += "%s \"%s\"\n" % (f,record.name)
# print the actual message
s += "%s %s: %s" % (self.formatPrefix[record.name],record.levelname,record.msg)
return s
# create the format prefix for the given package name
# (stored in self.formatPrefix[record.name])
# and return the first line to print
def getFormatPrefix(self,record):
depth = record.name.count(".")
self.formatPrefix[record.name] = " |" * (depth+1)
if depth == 0:
return "<--"
return "%so<--" % ( (" |" * depth)[:-1])
然后,您可以使用它来创建第一级记录器(此处为a).其余代码没有变化.
这是一个例子:
# use this to create the first level logger
def createTreeLogger(name,level=logging.DEBUG):
logger = logging.getLogger(name)
logger.setLevel(level)
ch = logging.StreamHandler()
ch.setLevel(level)
ch.setFormatter(TreeFormatter())
logger.addHandler(ch)
return logger
if __name__ == '__main__':
logger_a = createTreeLogger("a") # first level: use createLogger
# then create your loggers as always
logger_a_b = logging.getLogger("a.b")
logger_a_b_c = logging.getLogger("a.b.c")
logger_a.debug("One")
logger_a_b.warning("two")
logger_a_b.warning("three")
logger_a_b_c.critical("Four")
logger_a_b.warning("Five")
logger_a.warning("Six")
有趣的是,日志包内部将自动为子包使用相同的处理程序(a.b,a.b.c).因此,通过运行此代码,您将获得:
<-- "a"
| DEBUG: One
o<-- "a.b"
| | WARNING: two
| | WARNING: three
| o<-- "a.b.c"
| | | CRITICAL: Four
| | WARNING: Five
| WARNING: Six
一个缺点是,如果您有多个包层次结构,则日志会变得混乱.但TreeFormatter类很容易根据您的需要进行调整.