我可以在 `__exit__` 中提出异常吗?

Can I raise an exception in `__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?

Exceptions that occur during execution of this method will replace any exception that occurred in the body of the with statement.

https://docs.python.org/3/library/stdtypes.html#contextmanager.exit

我们可以查看 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)