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

Python装饰器如何访问默认参数并动态生成错误信息?

解决Python装饰器中的UnboundLocalError问题

问题原因

你遇到的UnboundLocalError是因为在wrapper函数内部对msg进行了赋值操作(msg = f"An error occurred in {func.__name__}"),Python会将msg视为局部变量。但在赋值之前,你先执行了if msg == ""的判断,此时局部变量msg还未被定义,因此抛出错误。

修复方案

我们可以通过以下方式解决:

  1. 避免修改外部作用域的msg变量,而是创建新变量存储最终错误信息
  2. 使用functools.wraps保留被装饰函数的元数据(如函数名、文档字符串)
  3. 确保返回被装饰函数的执行结果(原代码遗漏了这一点)

修复后的代码

from functools import wraps

def _exception_handler(msg=""):
    """自定义装饰器,为异常添加更丰富的上下文信息以简化调试"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                # 返回被装饰函数的执行结果
                return func(*args, **kwargs)
            except Exception as e:
                # 根据是否传入自定义消息生成最终错误提示
                if not msg:
                    error_msg = f"函数 {func.__name__} 执行时发生错误"
                else:
                    error_msg = msg
                # 抛出包含上下文的异常,保留原始异常栈
                raise Exception(f"{error_msg}: {e}") from e
        return wrapper
    return decorator

测试示例

1. 不传入自定义消息

@_exception_handler()
def divide(a, b):
    return a / b

divide(1, 0)

输出:

Exception: 函数 divide 执行时发生错误: division by zero

2. 传入自定义消息

@_exception_handler("用户数据处理失败")
def process_user_data(data):
    if not data.get("id"):
        raise ValueError("缺少用户ID")

process_user_data({})

输出:

Exception: 用户数据处理失败: 缺少用户ID

关键说明

  • 不修改外部msg变量:通过新建error_msg变量避免了局部变量遮蔽外部变量的问题
  • @wraps(func):确保被装饰函数的__name__、__doc__等元数据被保留,方便调试和自省
  • raise ... from e:保留原始异常的上下文,让traceback同时显示原始错误和自定义提示,便于定位问题

内容的提问来源于stack exchange,提问作者henhesu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:15:29