[Python-Dev] PEP 343 - Abstract Block Redux

Guido van Rossum gvanrossum at gmail.com
Mon May 16 20:54:54 CEST 2005


[Guido (responding to Fredrik Lundh's "intuitive -1" on PEP 343)]
> > Would it be better if we pulled back in the generator exit handling
> > from PEP 340? That's a pretty self-contained thing, and would let you
> > write try/finally around the yield.

[Nick Coghlan]
> That would be good, in my opinion. I updated PEP 3XX to use this idea:
> http://members.iinet.net.au/~ncoghlan/public/pep-3XX.html
> 
> With that update (to version 1.6), PEP 3XX is basically PEP 343, but injecting
> exceptions that occur into the template generator's internal frame instead of
> invoking next().

I'm in favor of the general idea, but would like to separate the error
injection and finalization API for generators into a separate PEP,
which would then compete with PEP 288 and PEP 325. I think the API
*should* be made public if it is available internally; I don't see any
implementation reasons why it would simplify the implementation if it
was only available internally.

Here are some issues to resolve in such a PEP.

- What does _inject_exception() return? It seems that it should raise
the exception that was passed into it, but I can't find this written
out explicitly.

- What should happen if a generator, in a finally or except clause
reached from _inject_exception(), executes another yield? I'm tempted
to make this a legitimate outcome (from the generator's perspective)
and reserve it for some future statement that implements the looping
semantics of PEP 340; the *_template decorator's wrapper class however
should consider it an error, just like other protocol mismatches like
not yielding the first time or yielding more than once in response to
next(). Nick's code in fact does all this right, Ijust think it should
be made explicit.

- TerminateIteration is a lousy name, since "terminate" means about
the same as "stop", so there could be legitimate confusion with
StopIteration. In PEP 340 I used StopIteration for this purpose, but
someone explained this was a poor choice since existing generators may
contain code that traps StopIteration for other purposes. Perhaps we
could use SystemExit for this purpose? Pretty much everybody is
supposed to let this one pass through since its purpose is only to
allow cleanup upon program (or thread) exit.

- I really don't like reusing __del__ as the method name for any kind
of destructor; __del__ has all sorts of special semantics (the GC
treats objects with a __del__ method specially).

- The all_lines() example jars me. Somehow it bugs me that its caller
has to remember to care about finalizing it. Maybe it's just not a
good example; I don't see what this offers over just writing the
obviously correct:

    for fn in filenames:
        with opening(fn) as f:
            for line in f:
                update_config(line)

even if using the template saves a line. I doubt the use case comes up
frequently enough to warrant abstracting it out. If I have to import
the template to save a line here, I just made my program a bit less
readable (since the first-time reader has to look up the definition of
the imported all_lines template) and I didn't even save a line unless
the template is used at least twice.

(Note that Nick's PEP contains two typos here -- it says "print lines"
where it should say "print line" and a bit later "print f" where again
it should say "print line".)

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


More information about the Python-Dev mailing list