[Python-Dev] with-statement heads-up

Guido van Rossum guido at python.org
Tue Feb 28 19:07:36 CET 2006


On 2/28/06, Mike Bland <mbland at acm.org> wrote:
> On 2/28/06, Guido van Rossum <guido at python.org> wrote:
> > I just realized that there's a bug in the with-statement as currently
> > checked in. __exit__ is supposed to re-raise the exception if there
> > was one; if it returns normally, the finally clause is NOT to re-raise
> > it. The fix is relatively simple (I believe) but requires updating
> > lots of unit tests. It'll be a while.
>
> Hmm.  My understanding was that __exit__ was *not* to reraise it, but
> was simply given the opportunity to record the exception-in-progress.

Yes, that's what the PEP said. :-(

Unfortunately the way the PEP is specified, the intended equivalence
between writing a try/except in a @contextmanager-decorated generator
and writing things out explicitly is lost. The plan was that this:

@contextmanager
def foo():
    try:
        yield
    except Exception:
        pass

with foo():
    1/0

would be equivalent to this:

try:
    1/0
except Exception:
    pass

IOW

with GENERATOR():
    BLOCK

becomes a macro call, and GENERATOR() becomes a macro definition; its
body is the macro expansion with "yield" replaced by BLOCK. But in
order to get those semantics, it must be possible for __exit__() to
signal that the exception passed into it should *not* be re-raised.

The current expansion uses roughly this:

  finally:
      ctx.__exit__(*exc)

and here the finally clause will re-raise the exception (if there was one).

I ran into this when writing unit tests for @contextmanager.

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


More information about the Python-Dev mailing list