[Python-Dev] Re: anonymous blocks

Guido van Rossum gvanrossum at gmail.com
Wed Apr 27 22:27:18 CEST 2005

[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.

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:
                yield var
            except Exception, err:
                print "ignored", var, ":", err.__class__.__name__

    block safeLoop([10, 5, 0, 20]) as x:
        print 1.0/x

This should print

    ignored 0 : ZeroDivisionError

I've been thinking of alternative signatures for the __next__() method
to handle this. We have the following use cases:

1. plain old next()
2. passing a value from continue EXPR
3. forcing a break due to a break statement
4. forcing a break due to a return statement
5. passing an exception EXC

Cases 3 and 4 are really the same; I don't think the generator needs
to know the difference between a break and a return statement. And
these can be mapped to case 5 with EXC being StopIteration().

Now the simplest API would be this: if the argument to __next__() is
an exception instance (let's say we're talking Python 3000, where all
exceptions are subclasses of Exception), it is raised when yield
resumes; otherwise it is the return value from yield (may be None).

This is somewhat unsatisfactory because it means that you can't pass
an exception instance as a value. I don't know how much of a problem
this will be in practice; I could see it causing unpleasant surprises
when someone designs an API around this that takes an arbitrary
object, when someone tries to pass an exception instance. Fixing such
a thing could be expensive (you'd have to change the API to pass the
object wrapped in a list or something).

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'll add this to the PEP as an alternative for now.

--Guido van Rossum (home page: http://www.python.org/~guido/)

More information about the Python-Dev mailing list