指定format时,自定义logging.Formatter的.属性无法初始化
问题描述
我实现了一个自定义logging.Formatter类MyFormatter,它支持额外的custom_property属性。但在配置该Formatter时,若同时指定format属性,通过.配置的custom_property无法完成初始化;若注释掉format配置项,.属性则能正常初始化自定义属性。
配置代码
"custom_formatter": { "()": MyFormatter, "style": "{", "datefmt": "%Y-%m-%d %H:%M:%S", "format": "<custom-format>", # <-- 移除后,'.'即可正常工作 ".": { "custom_property": "value" } }
Formatter实现代码
class MyFormatter(logging.Formatter): custom_property: str = "." def format(self, record: logging.LogRecord) -> str: # ... return super().format(record)
请问为何在指定format时,.属性无法生效?
原因分析与解决方案
核心原因
Python logging配置模块对format参数有特殊处理逻辑:当配置中包含format时,模块会优先基于内置的logging.Formatter完成基础实例的初始化,之后再尝试将实例转换为你指定的自定义类类型,这个过程会打断.属性的赋值流程。
具体来说:
- 当检测到
format键时,logging会先调用logging.Formatter的构造函数,传入format、style、datefmt等参数创建临时实例。 - 随后尝试将这个临时实例的类型转换为你通过
()指定的MyFormatter,但这个转换过程不会正确继承后续通过.设置的属性——因为.的属性赋值逻辑是在实例创建完成后执行的,而类型转换会覆盖或丢失这些未绑定的属性。 - 若没有
format参数,logging会直接通过你指定的()工厂类创建实例,此时.的属性赋值可以正常绑定到实例上。
解决方法
方法1:避免使用内置format配置键,改用自定义参数
修改自定义Formatter类,添加构造函数接收格式字符串,直接在配置中传递自定义参数而非format:
class MyFormatter(logging.Formatter): def __init__(self, fmt=None, custom_property=".", **kwargs): # 先处理自定义属性,再调用父类构造 self.custom_property = custom_property super().__init__(fmt=fmt, **kwargs) def format(self, record: logging.LogRecord) -> str: # ... return super().format(record)
对应的配置修改为:
"custom_formatter": { "()": MyFormatter, "style": "{", "datefmt": "%Y-%m-%d %H:%M:%S", "fmt": "<custom-format>", "custom_property": "value" }
方法2:在自定义Formatter构造函数中主动处理属性
如果一定要保留format配置,可以在自定义类的__init__中主动提取并设置自定义属性,避免被父类逻辑覆盖:
class MyFormatter(logging.Formatter): custom_property: str = "." def __init__(self, **kwargs): # 先提取自定义属性,再调用父类构造 self.custom_property = kwargs.pop('custom_property', self.custom_property) super().__init__(**kwargs) def format(self, record: logging.LogRecord) -> str: # ... return super().format(record)
此时配置可以保留.,或者直接将custom_property作为参数传递:
"custom_formatter": { "()": MyFormatter, "style": "{", "datefmt": "%Y-%m-%d %H:%M:%S", "format": "<custom-format>", "custom_property": "value" }
内容的提问来源于stack exchange,提问作者t3chb0t
相关产品推荐
相关产品推荐

