【发布时间】:2021-04-09 06:16:58
【问题描述】:
这是一个关于contextmanager 是如何工作的问题。
contextmanger 是一个装饰器,它调用装饰函数(生成器)两次,以构建__enter__ 和__exit__ 函数,供with 子句使用,到目前为止一切顺利。我不明白的是——当with 块内引发异常时,生成器内的except 块怎么能捕获它? p>
@contextmanager
def f():
try:
yield 'foo'
except Exception as e:
print('How can I ever reach here??')
print(e)
finally:
print('finally')
with f() as p:
print(p)
raise Exception('bar')
输出是
foo
How can I ever reach here??
bar
finally
我认为魔法发生在@contextmanager 中,因为如果我删除装饰器,并且只执行“yield inside try 块”,则生成器外部的异常不会在生成器内部捕获:
def f():
try:
yield 'foo'
except Exception as e:
print('How can I ever reach here??')
print(e)
finally:
print('finally')
g = f()
print(next(g))
raise Exception('bar')
输出是
foo
Traceback (most recent call last):
...
Exception: bar
我查看了contextlib.contextmanager 代码,但仍然无法弄清楚使用纯 python 代码如何实现这一点。关于我在这里错过的语言的一些基本知识?
【问题讨论】:
标签: python exception generator yield contextmanager