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

上下文管理器装饰方法中异常被静默忽略?代码未抛异常是Bug吗?

为什么上下文管理器内抛出的异常没有被传播?

这不是Bug,是你对上下文管理器的错误处理逻辑理解有误——问题出在finally块中的return语句上。

原因解析

Python中,如果finally块里存在return语句,它会覆盖并丢弃之前所有未处理的异常。你的代码里,__getitem__抛出的ValueError本来应该传播到上下文管理器外部,但finally中的return直接终止了上下文管理器的执行流程,异常被吞掉了,所以你看不到异常栈信息。

修正后的代码

只需要移除finally块里的return即可:

from contextlib import contextmanager

class Dataset:
    _getToRaise = False
    
    def __getitem__(self, index):
        if self._getToRaise:
            print("It is supposed to raise here")
            raise ValueError
        return 0
    
    @contextmanager
    def getToRaise(self):
        try:
            self._getToRaise = True
            print('Entering context manager')
            yield
        finally:
            print('Exiting context manager')
            self._getToRaise = False
    
d = Dataset()
with d.getToRaise():
    d[0]

修正后的运行结果

执行上述代码后,你会看到预期的异常输出:

Entering context manager
It is supposed to raise here
Exiting context manager
Traceback (most recent call last):
  File "test.py", line 22, in <module>
    d[0]
  File "test.py", line 8, in __getitem__
    raise ValueError
ValueError

补充说明

finally块的核心作用是保证清理逻辑(比如重置_getToRaise状态)无论是否发生异常都会执行,不需要通过return来结束它。Python会自动在finally块执行完成后,重新抛出之前捕获到的异常(如果存在)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:15:02