如何在类中使用loguru.catch装饰器?自定义日志类场景问题
解决方案
核心问题分析
你遇到的问题本质是:装饰器的@语法在类定义阶段就会执行,但你的logger实例是在Task类的__init__方法中才完成初始化的,类定义阶段logger作为实例属性还不存在,直接用@logger.catch会触发变量未定义的错误。
可行解决方法
方法1:动态给实例方法绑定装饰器
不需要修改MyLog类的逻辑,只在Task的初始化方法中,完成logger实例化后,手动将装饰器应用到目标方法上:
# test.py class Task: def __init__(self, filepath): my_log = MyLog(filepath) self.logger, self.task_error_log = my_log.producer_log() # 动态为目标方法添加catch装饰器 self.target_method = self.logger.catch(self.target_method) def target_method(self): # 你的业务逻辑代码 pass
这种方式完全适配你当前的日志类设计,灵活度高,适合filepath需要动态传入的场景。
方法2:调整MyLog类,让装饰器支持提前绑定参数
如果catch装饰器的核心逻辑只依赖call_filename,可以把producer_log改为类方法,让它返回绑定了参数的装饰器,这样就能在类定义阶段使用@语法:
# MyLog类修改示例 class MyLog: def __init__(self, filepath): self.filepath = filepath @classmethod def producer_log(cls, call_filename): # 原有logger初始化逻辑 logger = cls._init_logger(call_filename) # 重新实现catch装饰器,绑定call_filename def catch(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: logger.error(f"[{call_filename}] 执行出错: {str(e)}") raise return wrapper logger.catch = catch task_error_log = cls._init_task_error_log() return logger, task_error_log
之后在Task类中,若call_filename是固定值(比如当前文件test.py),可以提前初始化logger并使用装饰器:
# test.py logger, task_error_log = MyLog.producer_log("test.py") class Task: def __init__(self, filepath): self.task_error_log = task_error_log # 其他初始化逻辑 @logger.catch def target_method(self): # 业务逻辑代码 pass
这种方式适合call_filename固定的场景,能保持@装饰器的语法简洁性。
内容的提问来源于stack exchange,提问作者Coconut water
相关产品推荐
相关产品推荐

