如何缩进python记录器打印的多行消息?

Aiv*_*ven 10 python logging python-logging

当前行为:

DEBUG:package:123 > message with
multiple lines
foo bar
Run Code Online (Sandbox Code Playgroud)

想要的行为:

DEBUG:package:123 > message with
                    multiple lines
                    foo bar
Run Code Online (Sandbox Code Playgroud)

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

Arv*_*vin 8

现有答案很好地回答了缩进部分。但与原来相比,新的format实现没有正确处理其他字段(例如exec_info, ) 。stack_infologging.Formatter

以下实现基于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)
Run Code Online (Sandbox Code Playgroud)


Aiv*_*ven 2

最终得到自定义格式化程序,但 fmt 字符串中没有消息:

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
Run Code Online (Sandbox Code Playgroud)