[Python-Dev] with_traceback

Guido van Rossum guido at python.org
Fri Mar 2 02:45:56 CET 2007


[Summary: James Knight's idea can't work unless we copy the entire
stack, which is bad. Disregard my previous posts in this thread of a
few minutes ago. See the end of this post why.]

On 3/1/07, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> James Y Knight wrote:
>
> > It seems to me that a stack trace should always be attached to an
> > exception object at creation time
>
> Um. Yes. Well, that's certainly an innovative solution...

In the Python context perhaps, but given the Java precedent I would
hardly call it innovative.

> > The traceback won't necessarily be *useful*,
>
> Almost completely use*less*, I would have thought.
> The traceback is mostly used to find out where
> something went wrong, not where it went right (i.e.
> successful creation of the exception).

Which is one opcode before it is raised, in 99.99% of all cases.

> > creating the traceback is generally very expensive,
>
> I don't think so -- isn't it just a linked list
> of existing stack frames? That should be very cheap
> to create.

This is a difference between Python and Java that we should preserve.
Java's traceback is a string; Python's is a linked list of traceback
objects

> >  From http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html:
> >
> >>A throwable contains a snapshot of the execution stack of its
> >>thread at the time it was created.
>
> This would be a major and surprising change to Python
> users.
>
> It would also be considerably *more* expensive to implement
> than the current scheme, because it would require copying the
> entire stack, instead of just linking stack frames together
> as they are unwound during the search for an exception
> handler.

Oh bah, you're right. This sounds like a deal killer c.q. show shopper.

In my earlier responses forgot the details of how Python exceptions
work. You start with a traceback object pointing to the current frame
object (traceback objects are distinct from frame objects, they are
linked in the *opposite* direction, so no cycles are created); then
each time the exception bubbles up a stack frame, a new traceback
object pointing to the next frame object is inserted in front of the
traceback. This requires updating the traceback pointer each time we
bubble up a frame. Then when you catch the exception, the chain of
tracebacks points to all frames between the catching and the raising
frame (I forget whether catching frame is included).

Since this can conceivably be going on in parallel in multiple
threads, we really don't ever want to be sharing whatever object
contains the head of the chain of tracebacks since it mutates at every
frame bubble-up. I guess our next best option would be Glyph's
suggested object to represent a caught exception, which could indeed
be named "catch" per Greg's suggestion. The next-best option would be
to clone the exception object whenever it is raised, but that seems
wasteful in the normal case.

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


More information about the Python-Dev mailing list