You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在类中使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 02:58:22