Skip to content

Instantly share code, notes, and snippets.

@dstuebe
Created March 12, 2013 02:54
Show Gist options
  • Save dstuebe/5139919 to your computer and use it in GitHub Desktop.
Save dstuebe/5139919 to your computer and use it in GitHub Desktop.
Trying to put a generator inside a with statement. It seems it is not possible.
from exceptions import StopIteration, GeneratorExit
class WithThis(object):
"""
Open is a built in - can't override __exit__ or subclass it so wrap it :-(
"""
def __init__(self,this=None):
print " __init__"
if this is None:
this = {}
self.this = this
def __enter__(self):
print " __enter__"
return self.this
def __exit__(self, exctype, value, tb):
print " __exit__: %s,%s" % (exctype, value)
self.this.clear()
if exctype == StopIteration:
print 'Haha!'
return True
elif exctype == GeneratorExit:
print "Hoho!"
raise GeneratorExit
return False
else:
return True
def gen_with(this=None):
if this is None:
this = {}
things = ['eat','poop','you','cat']
for i, item in enumerate(things):
with WithThis(this=this) as ths:
ths[item] = i
yield ths
def gen_print(d=None):
print "GenPrint: '%s'" % d
def gen_error(d=None):
print "GenError: '%s'" % d
del d['not a key']
def coroutine(func):
"""From Beazley"""
def start(*arg, **kwargs):
g = func(*arg, **kwargs)
g.next()
return g
return start
@coroutine
def co_with(target, this=None):
if this is None:
this = {}
print "co_with ready to recieve file names"
i = 0
while True:
with WithThis(this=this) as ths:
thing = (yield)
ths[thing] = i
target.send(ths)
i += 1
@coroutine
def co_print():
print "co_print ready to recieve file names"
while True:
d = (yield)
print "CoPrint: %s" % d
@coroutine
def co_error():
print "co_error ready to recieve file names"
while True:
d = (yield)
print "CoError: %s" % d
del d['not a key']
d = {}
print "Try with a generator inside the with"
print "First case, no exceptions raised:"
g = gen_with(this=d)
for item in g:
gen_print(d)
g = gen_with(this=d)
print "Second case, Key Error causes the generator to Fail. With is not allowed to catch Generator Exit"
for item in g:
gen_error(d)
print "%%%%%%% Now try with coroutines %%%%%%%%%%"
d= {}
e = {}
co_without_error = co_with(co_print(), this=d)
co_with_error = co_with(co_error(), this = e)
things = ['eat','poop','you','cat']
print "First case, no exceptions"
for item in things:
co_without_error.send(item)
print "Second case, Cause a Key Error"
for item in things:
co_with_error.send(item)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment