如何在自定义Python类中扩展logging模块方法且不影响vars()输出?
解决自定义类扩展logging方法同时保持vars()干净的问题
我来帮你搞定这个需求!你想要给自定义Test类扩展logging模块的自定义级别print方法,同时要求调用vars()时只显示你自己定义的属性,不能把这个日志方法也包含进来对吧?先梳理下你尝试的三种方法的问题,再给出更优雅的实现方案:
现有方法的问题分析
方法一:绑定为实例属性
把logger.print赋值给实例属性self.print,虽然能直接调用,但vars()会把这个方法当作实例属性输出,不符合你“仅显示非logging方法属性”的要求。
# Test.py import logging logger = logging.getLogger('console') class Test: def __init__(self): self._some_obj = True self.print = logger.print # 绑定为实例属性 # main.py print(vars(Test())) # 输出 {'_some_obj': True, 'print': <bound method Logger.print of <Logger console (PRINT)>>}
方法二:设为类属性
将logger.print设为类属性后,vars()的输出确实干净了,但直接覆盖了Python内置的print方法,会导致代码中无法正常使用默认的打印功能,风险很高。
# Test.py import logging logger = logging.getLogger('console') class Test: print = logger.print # 覆盖了默认print方法 def __init__(self): self._some_obj = True # main.py print(vars(Test())) # 输出 {'_some_obj': True},但类的print被覆盖
方法三:编写包装方法
手动写包装方法虽然能避开前两个问题,但代码冗余度高,而且如果logger.print有可选参数(比如exc_info、extra等),你需要手动处理参数传递,非常不优雅。
# Test.py import logging logger = logging.getLogger('console') class Test: def __init__(self): self._some_obj = True def print(self, msg): # 包装方法,参数处理麻烦 logger.print(msg) # main.py print(vars(Test())) # 输出 {'_some_obj': True}
推荐方案:使用__getattr__魔法方法
Python的__getattr__方法会在访问实例上不存在的属性时被调用,利用这个特性,我们可以动态返回logger.print方法,既不会在vars()中留下痕迹,也不会覆盖默认方法,还能自动传递所有参数。
完整实现代码
首先确保你已经注册了自定义的PRINT日志级别(如果还没做的话),然后实现Test类:
# Test.py import logging # 注册自定义PRINT级别(级别值设为DEBUG+5,比DEBUG高一点) PRINT_LEVEL = logging.DEBUG + 5 logging.addLevelName(PRINT_LEVEL, 'PRINT') # 给Logger类添加print方法 def _logger_print(self, msg, *args, **kwargs): if self.isEnabledFor(PRINT_LEVEL): self._log(PRINT_LEVEL, msg, args, **kwargs) logging.Logger.print = _logger_print logger = logging.getLogger('console') class Test: def __init__(self): self._some_obj = True def __getattr__(self, name): # 当访问的属性是'print'时,返回logger的print方法并绑定当前实例上下文 if name == 'print': return logger.print.__get__(self, Test) # 其他属性按默认逻辑处理,抛出AttributeError raise AttributeError(f"'Test' object has no attribute '{name}'")
测试效果
# main.py from Test import Test t = Test() # 调用自定义日志方法,支持所有logger.print的参数 t.print("This is a custom log message", exc_info=True) # 查看vars()结果,仅显示自定义属性 print(vars(t)) # 输出 {'_some_obj': True} # 默认print方法依然可用 print("Default print works normally!")
方案优势
- vars()干净无冗余:
__getattr__是动态处理属性访问,没有给实例或类添加实际的属性,所以vars()只会显示你定义的_some_obj - 不覆盖默认方法:只有当实例上找不到
print属性时才会触发__getattr__,默认的print函数完全不受影响 - 参数自动传递:返回的是
logger.print的绑定方法,所有可选参数(如exc_info、extra)都能直接使用,无需手动处理 - Pythonic且简洁:利用Python的魔法方法特性,代码简洁优雅,避免了冗余的包装方法
内容的提问来源于stack exchange,提问作者als9xd
相关产品推荐
相关产品推荐

