block 内的 python 异常处理

标签 python python-3.x exception with-statement contextmanager

下面的代码是不是对python3的with语句和异常处理做错了什么?如果不是,编写预期输出的正确方法是什么?

from contextlib import contextmanager

@contextmanager
def test():
    print("Hello")
    yield
    print("goodbye")

try:
    with test():
        print("inside test")
        raise KeyError
except KeyError:
    print("KeyError")
else:
    print("else")
finally:
    print("finally")

输出是

Hello
inside test
KeyError
finally

期望输出是:

Hello
inside test
goodbye
KeyError
finally

我相信other people类似地写,希望在处理文件过程中出现异常时关闭文件。

我的python3版本是:

Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.version)
3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609]

最佳答案

with 管理的 block 内的异常语句通过 generator.throw() 传播到您的生成器上下文管理器如图PEP 343: "Generator Decorator" ,这会在生成器暂停的地方引发异常。换句话说,您应该将 yield 包装在 try/except 或 try/finally 中:

@contextmanager
def test():
    print("Hello")
    try:
        # The block of the with statement executes when the generator yields
        yield

    finally:
        print("goodbye")

引用official documentation关于主题:

...If an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred. Thus, you can use a tryexceptfinally statement to trap the error (if any), or ensure that some cleanup takes place. If an exception is trapped merely in order to log it or to perform some action (rather than to suppress it entirely), the generator must reraise that exception. Otherwise the generator context manager will indicate to the with statement that the exception has been handled, and execution will resume with the statement immediately following the with statement.

关于 block 内的 python 异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50715920/

相关文章:

python - Snakeviz 只显示一个功能

python - 如何在 python 中获取具有特定文件夹同级的特定文件夹

python - 关于lambda的另一个问题, "k"在这里是什么意思?

python-3.x - 带有 lambda 表达式的 python pickle 对象

c++ - 捕获构造函数抛出的异常似乎是不可能的

python - 如何更改 Matplotlib 表的透明度/不透明性?

python - Python lambda 捕获语义如何用于函数指针?

python - 如何使用 cmp 将排序从 python 2 转换为 python 3?

java - 从 NullPointerException 获取堆栈跟踪

java - JUnit 异常处理不起作用