finally中抛出的异常会覆盖try或except中的异常,成为最终传播的异常;应避免在finally中抛未处理异常,必要时用try捕获并记录;python 3.11+可用exceptiongroup保留两者。

如果在 finally 块中抛出了异常,它会覆盖 try 或 except 中已发生的异常(如果有),成为最终向外传播的异常。
finally 中的异常会压制前面的异常
Python 的异常处理机制规定:只要 finally 块中主动抛出异常(或执行了引发异常的操作),这个新异常就会“取代”之前 try 或 except 中尚未处理完的异常。原异常的信息会被丢弃,调用栈中只显示 finally 中的异常。
- 即使
try中发生了异常并进入except,只要finally抛异常,except里的修复逻辑可能根本没机会执行完 - 如果
except中已有return,但finally后续又抛异常,函数仍会以 finally 的异常结束,不会返回 - 示例:
>>> def f():
... try:
... raise ValueError("in try")
... except ValueError:
... print("caught")
... return "from except"
... finally:
... raise RuntimeError("in finally")
...
>>> f()
caught
Traceback (most recent call last):
File "", line 1, in
File "", line 8, in f
RuntimeError: in finally
避免在 finally 中抛出未处理的异常
finally 的本意是确保清理逻辑一定执行,不是用来做业务判断或可能失败的操作。应尽量让其中的代码“免疫”异常。
- 把可能出错的操作移出
finally,放到try/except中处理 - 若必须在
finally中调用可能失败的方法(如关闭文件、释放锁),应自行捕获其异常并记录,而不是放任传播 - 例如:
finally:
try:
resource.close()
except OSError as e:
logging.warning(f"Failed to close resource: {e}")
需要同时保留两个异常时用 ExceptionGroup(Python 3.11+)
如果确实需要反映“主异常 + 清理异常”两者,且运行环境支持 Python 3.11 及以上,可手动构造 ExceptionGroup。
- 需显式保存 try/except 中的异常,再与 finally 异常组合
- 实际场景较少,多数情况下应优先避免 finally 抛异常
- 不推荐为兼容性牺牲可读性,老版本 Python 无法识别 ExceptionGroup










