在生成器中使用上下文管理器有意义吗?

12 投票
1 回答
2383 浏览
提问于 2025-04-16 18:46
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

有没有办法让Python在for循环被中断时自动调用context()__exit__方法?或者有没有其他方法可以达到同样的目的?我对生成器和上下文管理器的了解让我怀疑这是否可能,但这让上下文管理器在生成器里显得没什么用,不是吗?我觉得在with块里面的yield语句应该引起警觉,上下文管理器的__exit__可能不会执行

1 个回答

18

好吧,你可以把yield放在context()函数里,并加上一个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

补充:如果你输入:help(contextmanager),它会显示一个“典型”的用法示例,里面就是把yield放在try/finally结构里。

撰写回答