2011-06-01 58 views
9
from contextlib import contextmanager 

@contextmanager 
def context(): 
    print "entering" 
    yield 
    print "exiting" 

def test(): 
    with context(): 
     for x in range(10): 
      yield x 

for x in test(): 
    if x == 5: 
     break # or raise 

输出:有没有一种有意义的方式来使用发生器内的上下文管理器?

entering 

有没有一种方法,使蟒蛇自动调用上下文的__exit__()方法时,for -loop中断?或者达到相同目标的其他方式?我对发生器和上下文管理器的了解让我怀疑这是不可能的,但是这使得上下文管理器在发生器内部毫无用处,不是吗?在我看来,with块内的yield声明应该引起红旗,上下文管理器__exit__可能不运行

回答

15

嗯,你可以包裹在上下文中的收益率()函数与一个try/finally从句:

from contextlib import contextmanager 

@contextmanager 
def context(): 
    print "entering" 
    try: 
     yield 
    finally: 
     print "exiting" 

def test(): 
    with context(): 
     for x in range(10): 
      yield x 

for x in test(): 
    if x == 5: 
     break # or raise 

输出:

entering 
exiting 

编辑:如果你尝试:帮助(contextmanager),它会显示它是“典型的”用例,它们用try/finally子句包装yield。

+1

+1为一个简单而有效的例子。 – jathanism 2011-06-01 15:32:21

+2

这正是你应该做的:循环'test()'被删除后,在'yield x'处引发'GeneratorExit()'。这反过来又打破了':with:for:'块。然后上下文管理器再次捕获'GeneratorExit()'并在'context'的yield处引发它 - 这就是你必须捕获它的地方,否则'context'就会在那里结束(毕竟它也是一个生成器,所以这个异常无声地结束)而不进行清理。该文档声明:“因此,您可以使用try ... except ... finally语句来捕获错误(如果有的话),或确保进行一些清理” – 2011-06-01 15:54:16

相关问题