python 指定“format”时,未通过“.”初始化自定义格式化程序属性

kokeuurv  于 2023-10-14  发布在  Python
关注(0)|答案(1)|浏览(67)

我有一个自定义的logging.Formatter,它支持一些额外的属性,但是当我也指定format属性时,它们不会被初始化。如果我注解掉format行,.属性将正确地替换其自定义属性。

"custom_formatter": {
                "()": MyFormatter,
                "style": "{",
                "datefmt": "%Y-%m-%d %H:%M:%S",
                "format": "<custom-format>", # <-- when removed, then the '.' works
                ".": {
                    "custom_property": "value"
                }
            }

为什么使用format.不工作?
格式化程序是这样实现的:

class MyFormatter(logging.Formatter):
    custom_property: str = "."

    def format(self, record: logging.LogRecord) -> str:
        # ...
        return super().format(record)
55ooxyrt

55ooxyrt1#

我发现了bug。显然,该属性的名称已从format更改为fmt,并且旧示例在其代码中显示format,当使用此属性时,处理.字典的代码不会执行,因为初始化福尔斯会返回到异常处理程序,并跳过通常执行.的其余代码
这是错误处理程序:
https://github.com/python/cpython/blob/main/Lib/logging/config.py#L670

def configure_formatter(self, config):
        """Configure a formatter from a dictionary."""
        if '()' in config:
            factory = config['()'] # for use in exception handler
            try:
                result = self.configure_custom(config)
            except TypeError as te:
                if "'format'" not in str(te):
                    raise
                #Name of parameter changed from fmt to format.
                #Retry with old name.
                #This is so that code can be used with older Python versions
                #(e.g. by Django)
                config['fmt'] = config.pop('format')
                config['()'] = factory
                result = self.configure_custom(config)

这是在result = c(**kwargs)行抛出错误的代码,因此跳过了props的处理,因为config不再包含.,因为它在第一次尝试时就从字典中弹出了!
https://github.com/python/cpython/blob/main/Lib/logging/config.py#L480

def configure_custom(self, config):
        """Configure an object with a user-supplied factory."""
        c = config.pop('()')
        if not callable(c):
            c = self.resolve(c)
        props = config.pop('.', None) # <-- removes '.' making it impossible to use it on the second try!
        # Check for valid identifiers
        kwargs = {k: config[k] for k in config if valid_ident(k)}
        result = c(**kwargs)
        if props:
            for name, value in props.items():
                setattr(result, name, value)
        return result

props = config.pop('.', None)行应该在result = c(**kwargs)之后。

相关问题