Lauritz V. Thaulow
Lauritz V. Thaulow

Reputation: 50995

Is there a meaningful way to use context managers inside generators?

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

output:

entering

Is there a way to make python automatically invoke the __exit__ method of context() when the for-loop is interrupted? Or some other way of achieving the same aim? What I know about generators and context managers makes me suspect it's not possible, but this makes context managers rather useless inside generators, doesn't it? It seems to me, a yield statement inside a with block should raise a red flag, context manager __exit__ may not run.

Upvotes: 12

Views: 2406

Answers (1)

Gerrat
Gerrat

Reputation: 29690

Well, you could wrap the yield in context() function with a try/finally clause:

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

output:

entering
exiting

Edit: If you try a: help(contextmanager), it will show it's "typical" useage example where they wrap the yield with a try/finally clause.

Upvotes: 18

Related Questions