Python装饰器如何访问默认参数并动态生成错误信息?
解决Python装饰器中的UnboundLocalError问题
问题原因
你遇到的UnboundLocalError是因为在wrapper函数内部对msg进行了赋值操作(msg = f"An error occurred in {func.__name__}"),Python会将msg视为局部变量。但在赋值之前,你先执行了if msg == ""的判断,此时局部变量msg还未被定义,因此抛出错误。
修复方案
我们可以通过以下方式解决:
- 避免修改外部作用域的
msg变量,而是创建新变量存储最终错误信息 - 使用
functools.wraps保留被装饰函数的元数据(如函数名、文档字符串) - 确保返回被装饰函数的执行结果(原代码遗漏了这一点)
修复后的代码
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
相关产品推荐
相关产品推荐

