Python中的多行日志记录

时间:2014-04-08 10:44:00

标签: python logging python-3.x

我使用Python 3.3.5和日志记录模块将信息记录到本地文件(来自不同的线程)。在某些情况下,我希望输出一些额外的信息,而不确切知道该信息是什么(例如,它可能只是一行文字或字典)。

我想要做的是在写完日志记录后将这些附加信息添加到我的日志文件中。此外,仅当日志级别为错误(或更高)时才需要附加信息。

理想情况下,它看起来像:

2014-04-08 12:24:01 - INFO     - CPU load not exceeded
2014-04-08 12:24:26 - INFO     - Service is running
2014-04-08 12:24:34 - ERROR    - Could not find any active server processes
Additional information, might be several lines.
Dict structured information would be written as follows:
key1=value1
key2=value2
2014-04-08 12:25:16 - INFO     - Database is responding

如果没有编写自定义日志格式化程序,我找不到符合我要求的内容。我已经阅读了关于过滤器和上下文的内容,但这似乎并不是一个很好的匹配。

或者,我可以使用标准I / O写入文件,但大部分功能已经存在于Logging模块中,而且它的线程安全。

任何输入都将不胜感激。如果确实需要自定义日志格式化程序,那么任何关于从哪里开始的指针都会非常棒。

4 个答案:

答案 0 :(得分:7)

请记住,许多人认为多行日志记录消息是一种不好的做法,您可以使用extra属性并使用自定义格式化程序将内容附加到要显示的消息上(取查看日志包documentation中'extra'的用法。

import logging

class CustomFilter(logging.Filter):
    def filter(self, record):
        if hasattr(record, 'dct') and len(record.dct) > 0:
            for k, v in record.dct.iteritems():
                record.msg = record.msg + '\n\t' + k + ': ' + v
        return super(CustomFilter, self).filter(record)

if __name__ == "__main__":
    logging.getLogger().setLevel(logging.DEBUG)
    extra_logger = logging.getLogger('extra_logger')
    extra_logger.setLevel(logging.INFO)
    extra_logger.addFilter(CustomFilter())
    logging.debug("Nothing special here... Keep walking")
    extra_logger.info("This shows extra",
                      extra={'dct': {"foo": "bar", "baz": "loren"}})
    extra_logger.debug("You shouldn't be seeing this in the output")
    extra_logger.setLevel(logging.DEBUG)
    extra_logger.debug("Now you should be seeing it!")

该代码输出:

DEBUG:root:Nothing special here... Keep walking
INFO:extra_logger:This shows extra
        foo: bar
        baz: loren
DEBUG:extra_logger:Now you should be seeing it!

我仍然建议您在自定义过滤器中调用super的{​​{1}}函数,主要是因为这是决定是否显示消息的函数(例如,如果您的记录器的级别设置为filter,并使用logging.INFO记录某些内容,不应该看到该消息,如上例所示)

答案 1 :(得分:3)

我只需在输出文本中添加\n个符号。

答案 2 :(得分:0)

我在定义LogFormatter字符串时似乎犯了一个小错误:由于意外地转义了换行符,我错误地认为不可能将多行输出写入日志文件。

向@Barafu表示欢呼(这就是我给他正确答案的原因)。

以下是示例代码:

import logging
lf = logging.Formatter('%(levelname)-8s - %(message)s\n%(detail)s')
lh = logging.FileHandler(filename=r'c:\temp\test.log')
lh.setFormatter(lf)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
log.addHandler(lh)
log.debug('test', extra={'detail': 'This is a multi-line\ncomment to test the formatter'})

结果输出如下所示:

DEBUG    - test
This is a multi-line
comment to test the formatter

警告:

如果没有要记录的详细信息,并且您传递一个空字符串,则记录器仍将输出换行符。因此,剩下的问题是:我们怎样才能使这个有条件?

一种方法是在实际记录信息之前更新记录格式化程序,如here所述。

答案 3 :(得分:0)

我在较小的应用程序中使用了一个简单的分线器:

Working Directory

请注意,这不是线程安全的,应该只能在日志量日志应用程序中使用。

但是,您几乎可以输出任何日志,因为它将保留您的格式。例如,我已使用它来输出使用以下格式设置的JSON API响应:for line in logmessage.splitlines(): writemessage = logtime + " - " + line + "\n" logging.info(str(writemessage))