【问题标题】:python exception handling inside with block带有块的python异常处理
【发布时间】:2018-11-15 21:00:00
【问题描述】:

下面的代码在with语句和python3的异常处理上有什么问题吗?如果不是,编写预期输出的正确方法是什么?

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]

【问题讨论】:

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


    【解决方案1】:

    with 语句控制的块中的异常通过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的主题:

    ...如果块中发生未处理的异常,则它会在生成器内部在 yield 发生的点处重新引发。因此,您可以使用tryexceptfinally 语句来捕获错误(如果有),或者确保进行一些清理。如果捕获异常只是为了记录它或执行某些操作(而不是完全抑制它),则生成器必须重新引发该异常。否则,生成器上下文管理器将向with 语句指示异常已被处理,并且将继续执行紧跟with 语句之后的语句。

    【讨论】:

    • 我明白了...我在编写 test() 时并没有想得那么深。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多