[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