如何使Python Logger打印的多行消息缩进?

8

当前行为:

DEBUG:package:123 > message with
multiple lines
foo bar

期望的行为:

DEBUG:package:123 > message with
                    multiple lines
                    foo bar

DEBUG:package:123 可能具有不同的宽度,因此在将其发送到记录器之前无法调整消息。


1
你是如何记录这些行的?你是将它们记录为三个单独的行吗? - Chris Doyle
似乎最简单的方法是在消息开头加上\r\n,这样所有所需对齐的元素都将左对齐。虽然不完全符合要求的功能,但也许可以非常简单地实现目标。 - meshtron
4个回答

6

现有的回答已经很好地回答了缩进部分。但是与原始的 logging.Formatter 相比,新的 format 实现未正确处理其他字段(例如 exec_infostack_info)。

以下实现基于 simonzack 的回答,并重用原始格式化程序以最小化副作用。

[编辑2021-11] 它还通过后处理格式化消息而不是预处理来正确处理格式化值。

class MultiLineFormatter(logging.Formatter):
    """Multi-line formatter."""
    def get_header_length(self, record):
        """Get the header length of a given record."""
        return len(super().format(logging.LogRecord(
            name=record.name,
            level=record.levelno,
            pathname=record.pathname,
            lineno=record.lineno,
            msg='', args=(), exc_info=None
        )))

    def format(self, record):
        """Format a record with added indentation."""
        indent = ' ' * self.get_header_length(record)
        head, *trailing = super().format(record).splitlines(True)
        return head + ''.join(indent + line for line in trailing)

2

在格式字符串中没有消息的情况下使用自定义格式化程序:

import textwrap

class Formatter(logging.Formatter):
    def __init__(self):
        super(Formatter, self).__init__(fmt="%(levelname)-8s %(name)20s:%(lineno)-3d > ")

    def format(self, record):
        header = super(Formatter, self).format(record)
        msg = textwrap.indent(record.message, ' ' * len(header)).strip()
        return header + msg

2
这是Aiven更现代化、更灵活的版本。
class MultiLineFormatter(logging.Formatter):
    def format(self, record):
        message = record.msg
        record.msg = ''
        header = super().format(record)
        msg = textwrap.indent(message, ' ' * len(header)).lstrip()
        record.msg = message
        return header + msg

为了使用此功能:
formatter = MultiLineFormatter(
    fmt='%(asctime)s %(levelname)-8s %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
)
log_handler = logging.StreamHandler()
log_handler.setFormatter(formatter)

0

修改了aiven的版本以使其正常工作。

class Formatter(logging.Formatter):
    def __init__(self, format_str):
        super(Formatter, self).__init__(fmt=format_str)

    def format(self, record):
        message = record.msg
        record.msg = ''
        header = super(Formatter, self).format(record)
        msg = textwrap.indent(message, ' ' * len(header)).strip()
        record.msg = message
        return header + msg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接