Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 765
Lauritz V. Thaulow Avatar asked Jun 01 '11 15:06

Lauritz V. Thaulow


Video Answer


1 Answers

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.

like image 125
Gerrat Avatar answered Nov 11 '22 04:11

Gerrat