首页 > 解决方案 > 我可以在 `__exit__` 中引发异常吗?

问题描述

我可以在__exit__方法中引发异常吗?如果是这样,这个异常会传播到with块外吗?

例子:

class X:
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        raise MyException()


with X() as x:
    pass

// What happens here? Is `MyException` propagated up the stack?

标签: pythonwith-statement

解决方案


执行此方法期间发生的异常将替换 with 语句主体中发生的任何异常。

https://docs.python.org/3/library/stdtypes.html#contextmanager。出口

我们可以看到with-statement了解更多细节。无论SUITE是否抛出异常,所引发的异常__exit__总是被抛出给调用者。

with EXPRESSION as TARGET:
    SUITE

在语义上等价于:

manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False

try:
    TARGET = value
    SUITE
except:
    hit_except = True
    if not exit(manager, *sys.exc_info()):
        raise
finally:
    if not hit_except:
        exit(manager, None, None, None)

推荐阅读