python – 子类化logging.Formatter更改logging.Formatter的默认行为

我在记录器中添加了两个带有不同格式化程序的处理程序.第一个需要子类化logging.Formatter来进行自定义格式化.默认格式化程序足以满足第二个处理程序的需要.

假设第一个格式化程序只是从消息中删除换行符.以下脚本说明了看似奇怪的行为:

import logging

logger = logging.getLogger(__name__)

class CustomFormatter(logging.Formatter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    def format(self, record):
        record.msg = record.msg.strip().replace('\n', ' ')
        return super().format(record)

h1 = logging.StreamHandler()
formatter1 = CustomFormatter(fmt=None, datefmt=None)
h1.setFormatter(formatter1)
logger.addHandler(h1)

h2 = logging.StreamHandler()
formatter2 = logging.Formatter(fmt=None, datefmt=None)
h2.setFormatter(formatter2)
logger.addHandler(h2)

logger.warning('string with\nmultiple lines')

这输出如下:

string with multiple lines
string with multiple lines

我期待这个:

string with multiple lines
string with 
multiple lines

第二个格式化程序不应该实现CustomFormatter的行为,但它确实如此.当我颠倒处理程序添加到记录器的顺序时,不会发生这种情况.

除非我误解了子类,否则不应该通过覆盖子类中的方法来改变基类的行为.当我覆盖除logging.Formatter之外的类的方法时,这似乎不是问题.

这是日志模块中的错误,还是我在这里遗漏了什么?

最佳答案 这条线是你的堕落:

record.msg = record.msg.strip().replace('\n', ' ')

您将已清理的字符串重新分配给记录,该记录由连接到记录器的所有剩余处理程序/格式化程序使用.复制记录,它的工作原理:

import logging
from copy import copy

logger = logging.getLogger(__name__)

class CustomFormatter(logging.Formatter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    def format(self, record):
        record = copy(record)
        record.msg = record.msg.strip().replace('\n', ' ')
        return super().format(record)

h1 = logging.StreamHandler()
formatter1 = CustomFormatter(fmt=None, datefmt=None)
h1.setFormatter(formatter1)
logger.addHandler(h1)

h2 = logging.StreamHandler()
formatter2 = logging.Formatter(fmt=None, datefmt=None)
h2.setFormatter(formatter2)
logger.addHandler(h2)

logger.warning('string with\nmultiple lines')

输出

string with multiple lines
string with
multiple lines
点赞