[Python-Dev] Merging PEP 310 and PEP 340-redux?
Guido van Rossum
gvanrossum at gmail.com
Tue May 10 17:47:06 CEST 2005
[Alex]
> I like this. The only aspect of other proposals that I would sorely
> miss here, would be the inability for abc.__exit__ to deal with
> exceptions raised in BLOCK (or, even better, a separate specialmethod
> on abc called in lieu of __exit__ upon exceptions). Or am I missing
> something, and would this give a way within abc.__exit__ to examine
> and possibly ``unraise'' such an exception...?
See my followup to Nick. I'm not worried about unraising exceptions.
The only way to mess with the exception from code in a finally-suite
is to raise another exception, and we can't really prevent that.
However (I forgot this in the response to Nick) unless/until we
augment generators in some way the generator can't easily see the
exception flag.
[me]
> > can write a relatively straightforward decorator, call it
> > @with_template, that endows a generator with the __enter__ and
> > __exit__ methods, so you can write all the examples (except
> > auto_retry(), which was there mostly to make a point) from PEP 340
> > like this:
> >
> > @with_template
> > def opening(filename, mode="r"):
> > f = open(filename, mode)
> > yield f
> > f.close()
> >
> > and so on. (Note the absence of a try/finally block in the generator
> > -- the try/finally is guaranteed by the with-statement but not by the
> > generator framework.)
[Alex]
> I must be thick this morning, because this relatively straightforward
> decorator isn't immediately obvious to me -- care to show me how
> with_template gets coded?
Here's a sketch:
class Wrapper(object):
def __init__(self, gen):
self.gen = gen
self.state = "initial"
def __enter__(self):
assert self.state == "initial"
self.state = "entered"
try:
return self.gen.next()
except StopIteration:
self.state = "error"
raise RuntimeError("template generator didn't yield")
def __exit__(self):
assert self.state == "entered"
self.state = "exited"
try:
self.gen.next()
except StopIteration:
return
else:
self.state = "error"
raise RuntimeError("template generator didn't stop")
def with_template(func):
def helper(*args, **kwds):
return Wrapper(func(*args, **kwds))
return helper
@with_template
def opening(filename, mode="r"):
f = open(filename) # Note that IOError here is untouched by Wrapper
yield f
f.close() # Ditto for errors here (however unlikely)
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-Dev
mailing list