当前行为:
DEBUG:package:123 > message with
multiple lines
foo bar
想要的行为:
DEBUG:package:123 > message with
multiple lines
foo bar
DEBUG:package:123
的宽度可以不同,因此无法在将消息发送到记录器之前对其进行调整。
答案 0 :(得分:1)
最后使用自定义格式化程序,在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
答案 1 :(得分:1)
这是更加现代化和灵活的 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)
答案 2 :(得分: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
答案 3 :(得分:0)
现有答案很好地回答了缩进部分。但是与原始 format
相比,新的 exec_info
实现没有正确处理其他字段(例如 stack_info
、logging.Formatter
)。
以下实现基于 simonzack's answer 并重用原始格式化程序以尽量减少副作用。
class MultiLineFormatter(logging.Formatter):
"""Multi-line formatter."""
def get_header_length(self, record):
"""Get the header length of a given record."""
record = copy.copy(record)
record.msg = ''
record.exc_info = None
record.exc_text = None
record.stack_info = None
header = super().format(record)
return len(header)
def format(self, record):
"""Format a record with added indentation."""
message = record.msg
# For now we only indent string typed messages
# Other message types like list or bytes won't be touched
if isinstance(message, str):
msgs = message.splitlines(True)
if len(msgs) > 1:
header_len = self.get_header_length(record)
# Indent lines (except the first line)
indented_message = msgs[0] + ''.join(map(
lambda m: ' ' * header_len + m if m != '\n' else m, msgs[1:]))
# Use the original formatter since it handles exceptions well
record.msg = indented_message
formatted_text = super().format(record)
# Revert to keep the msg field untouched
# As other modules may capture the log for further processing
record.msg = message
return formatted_text
return super().format(record)