[Python-Dev] Re: anonymous blocks

Phillip J. Eby pje at telecommunity.com
Wed Apr 27 22:59:46 CEST 2005


At 01:27 PM 4/27/05 -0700, Guido van Rossum wrote:
>[Phillip Eby]
> > Very nice.  It's not clear from the text, btw, if normal exceptions can be
> > passed into __next__, and if so, whether they can include a traceback.  If
> > they *can*, then generators can also be considered co-routines now, in
> > which case it might make sense to call blocks "coroutine blocks", because
> > they're basically a way to interleave a block of code with the execution of
> > a specified coroutine.
>
>The PEP is clear on this: __next__() only takes Iteration instances,
>i.e., StopIteration and ContinueIteration. (But see below.)
>
>I'm not sure what the relevance of including a stack trace would be,
>and why that feature would be necessary to call them coroutines.

Well, you need that feature in order to retain traceback information when 
you're simulating threads with a stack of generators.  Although you can't 
return from a generator inside a nested generator, you can simulate this by 
keeping a stack of generators and having a wrapper that passes control 
between generators, such that:

     def somegen():
         result = yield othergen()

causes the wrapper to push othergen() on the generator stack and execute 
it.  If othergen() raises an error, the wrapper resumes somegen() and 
passes in the error.  If you can only specify the value but not the 
traceback, you lose the information about where the error occurred in 
othergen().

So, the feature is necessary for anything other than "simple" (i.e. 
single-frame) coroutines, at least if you want to retain any possibility of 
debugging.  :)


>But... Maybe it would be nice if generators could also be used to
>implement exception handling patterns, rather than just resource
>release patterns. IOW, maybe this should work:
>
>     def safeLoop(seq):
>         for var in seq:
>             try:
>                 yield var
>             except Exception, err:
>                 print "ignored", var, ":", err.__class__.__name__
>
>     block safeLoop([10, 5, 0, 20]) as x:
>         print 1.0/x

Yes, it would be nice.  Also, you may have just come up with an even better 
word for what these things should be called... patterns.  Perhaps they 
could be called "pattern blocks" or "patterned blocks".  Pattern sounds so 
much more hip and politically correct than "macro" or even "code block".  :)


>An alternative that solves this would be to give __next__() a second
>argument, which is a bool that should be true when the first argument
>is an exception that should be raised. What do people think?

I think it'd be simpler just to have two methods, conceptually 
"resume(value=None)" and "error(value,tb=None)", whatever the actual method 
names are.



More information about the Python-Dev mailing list