【问题标题】:how to indent multiline message printed by python logger?如何缩进python记录器打印的多行消息?
【发布时间】:2020-02-23 16:58:56
【问题描述】:

当前行为:

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

想要的行为:

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

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

【问题讨论】:

  • 你是如何记录这些行的?您是否将它们记录为 3 个单独的行?
  • 似乎最简单的做法是以\r\n 开头的消息,因此所有所需的对齐元素都是左对齐的。不完全是要求的功能,但可能非常简单地实现了目标。

标签: python logging python-logging


【解决方案1】:

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

以下实现基于simonzack's answer,并重用原始格式化程序以最大程度地减少副作用。

[edit 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】:

    这里是 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)
    

    【讨论】:

      【解决方案3】:

      修改了 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
      

      【讨论】:

        【解决方案4】:

        以自定义格式化程序结束,而 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-02
          • 1970-01-01
          • 1970-01-01
          • 2017-11-02
          • 1970-01-01
          相关资源
          最近更新 更多