[Python-Dev] "with" use case: exception chaining

Ka-Ping Yee python-dev at zesty.ca
Thu May 12 21:02:29 CEST 2005


> - Ka-ping Yee thinks we need separate entry points for the exceptional
>   and the normal termination case.  I disagree; this would end up in
>   unnecessary duplication of code (or boilerplate to equate the two
>   methods) in most cases.  The whole *point* is that finally gets to
>   do its clean-up act regardless of whether an exception is being
>   processed or not.

Okay, let me back up for a second.  My suggestion responded to your
reply to Steve Bethard's example about exception handling.  The point
of the suggestion is that *if* we are going to let "with" do exception
handling, it should be done in a separate method.  I didn't mean to
imply that __finally__ should be skipped.

This brings us back to the question of whether "with" should be able
to handle exceptions.  On this, you wrote:

> For try/finally we have a large body of use cases that just scream for
> abstraction. I'm not convinced that we have the same for try/except.

So let's look at some use cases.  I've thought of two; the first one is
nice and simple, and the second one is messier so i'll discuss it in a
separate message.

Example 1: Exception Chaining.

As has been previously discussed, the information from an exception can
be lost when the handling of the exception runs into a problem.  It is
often helpful to preserve the original reason for the problem.

Suppose, by convention, that the "reason" attribute on exception objects
is designated for this purpose.  The assignment of this attribute can be
conveniently abstracted using a "with" clause as follows:

    try:
        # ... risky operation ...
    except:
        with reason(sys.exc_info()):
            # ... cleanup ...

The "with reason" construct would be implemented like this:

    class reason:
        def __init__(self, etype, evalue, etb):
            self.reason = etype, evalue, etb

        def __except__(self, etype, evalue, etb):
            evalue.reason = self.reason
            raise etype, evalue, etb

(Other possible names for "reason" might be "cause" or "context".)


-- ?!ng


More information about the Python-Dev mailing list