(六)自定义错误、重新抛出与异常链
底层只知道某个文本不能转成整数,记录读取层还知道“它是第几条记录”。可以在这一层增加信息,同时保留原始原因:
# 业务错误沿用 ValueError 的类别,增加记录位置的说明。
class RecordError(ValueError):
pass
def read_minutes(text, number):
try:
return int(text)
except ValueError as cause:
raise RecordError(f"第 {number} 条记录的分钟数错误") from cause
try:
read_minutes("很多", 2)
except RecordError as error:
print(error)
print(type(error.__cause__).__name__)输出“第 2 条记录的分钟数错误”和 ValueError。raise ... from cause 把两层错误连接起来,traceback 可以同时指出底层失败和业务说明,__cause__ 则保存显式给出的原因。
在 except 中只写 raise,表示把当前接收到的异常继续交出去。例如某层关闭临时资源后仍希望上层决定怎样提示,就完成清理再重新抛出。raise ... from None 会隐藏隐式异常上下文的显示;排查解析失败时,保留来源通常更容易找到具体数据问题。