[Python-Dev] PEP 344: Exception Chaining and Embedded Tracebacks

Phillip J. Eby pje at telecommunity.com
Tue May 17 18:12:48 CEST 2005


At 07:41 AM 5/17/2005 -0700, Guido van Rossum wrote:
>Consider
>
>     try:
>         BLOCK
>     except EXCEPTION, VAR:
>         HANDLER
>
>I'd like to see this translated into
>
>     try:
>         BLOCK
>     except EXCEPTION, VAR:
>         __context = VAR
>         try:
>             HANDLER
>         except Exception, __error:
>             __error.__context__ = __context
>             raise
>
>i.e. the context is set only upon *leaving* the handler. (The
>translation for finally is hairier but you get the idea at this
>point.)
>
>My intuition prefers this over Ping's solution because HANDLER could
>easily invoke code that (after many stack levels deep) raises and
>catches many exceptions, and I'd hate to see all those be bothered by
>the context (far down on the stack) that is irrelevant.

This seems intuitively correct to me as well.  If an error occurs in an 
error handler, you want the system to add the context for you.  If you're 
writing a handler that creates a replacement exception, you don't have to 
manually wrap the current exception - the system will add it for you when 
the replacement exception leaves the handler.  In both use cases, you want 
the new exception to be prominent, and the old exception is for digging 
deeper into the matter.  Very nice.

Hm.  What about code like this (made-up) example, though?

     def __getattr__(self,attr):
         try:
             return self.__auxattrs[attr]
         except KeyError:
             raise AttributeError,attr

Under this proposal, IIUC, you would get the context exception for the 
original KeyError, but it's "as designed".  In order to get rid of the 
context traceback, you'd have to write:

     def __getattr__(self,attr):
         try:
             return self.__auxattrs[attr]
         except KeyError:
             pass
         raise AttributeError,attr

Which isn't a big deal, but there's a lot of existing code that follows the 
first form, that would lead to a kind of "traceback spam".


>BTW, please study how the traceback is built up. I believe that if we
>store the traceback in the exception instance, we have to update the
>__traceback__ attribute each time we pop a stack level.

Yes; using .tb_next to build a linked list that goes "towards the exception 
frame".  But at least the context exception doesn't need that, since the 
context traceback can reasonably end at the frame where it was caught.



More information about the Python-Dev mailing list