[Python-3000] self-contained exceptions

Guido van Rossum guido at python.org
Tue Jan 2 01:30:22 CET 2007


On 1/1/07, tomer filiba <tomerfiliba at gmail.com> wrote:
> a while back some people suggested having the traceback
> as an attribute of the exception object, which allows for
> nested exceptions.

PEP 344, to be precise.

> i would also like to note that having the traceback part of
> the exception object allows the exception to print itself,
> i.e., its repr would format the traceback text on it's own.

I'm not sure that's an improvement. I like to b able to have different
ways of formatting exceptions. And a repr() that's as long as a
typical traceback isn't a great idea either. Note that currently
there's nothing to prevent tracebacks from having a repr() that prints
the exception, and yet this isn't what it does.

> this makes sys.excepthook unnecessary,

Not at all. sys.excepthook can do other things besides formatting the
exception, and when it does format the exception, it can do so in any
number of interesting alternative ways (e.g. cgitb.py).

> as well as
> traceback.format_exception (which i greatly dislike).

Why? Because it once insulted you?

> even if the exception's repr would raise an exception
> (recursion limit, etc.), that exception would be a builtin
> one, so we won't end up in a repr-exception-loop.
>
> with this approach, sys.excepthook is needless, or at least
> simplified greatly (just print repr(exc)). for example, exceptions
> raised by RPyC have a special attribute to them -- remote_traceback,
> which is the text of the remote traceback. currently i have to
> replace excepthook to have it displayed with the local exception
> traceback, which is means just importing RPyC messes with
> your interpreter's internals, and may cause problems when
> another library installs its own hook.
>
> apart from self-repr'ing, nested exceptions are very useful too:
>
> try:
>     foo()
> except Exception, ex:
>     raise MyException("something happened", nested = ex)

It really looks like you've never read PEP 344, or you wouldn't be
introducing a different way to spell what it already proposes.

> so that when i pdb.pm() my code, i can inspect the inner
> exception too (which is desirable of course).
>
> the major argument against having the traceback part of
> the exception object was increasing memory consumption,
> so that exceptions are no longer "light weight" (as used by
> StopIteration, etc.)

Where did you hear this? It is not *my* objection.

> i don't see why this argument stands. the traceback object
> exists either way, the only question is in what namespace
> it exists, and the fact it may "live longer" than necessary,
> i.e., the traceback exists for as long as the exception object
> exists.
>
> i don't think it's really that bad. first, for StopIteration, the exception
> object is decref()ed immediately after being raised. moreover,
> since no one is expected to see that traceback, it can be set
> directly to None, i.e., a PyErr_SetStopIter() function which sets
> exc.traceback to None internally.
>
> other than that, you *want* to keep the traceback alive. therefore,
> i suggest adding two new attributes to the exception class:
> * traceback - the traceback object, or None
> * nested - nested ("inner") exception, or None
>
> Exception.__repr__ will be extended to formatting the
> traceback (if not None) and formatting all the nested
> exceptions (+ detect recursion).
>
> this may be an expensive operation, but as it only happens
> when the exceptions is printed to stderr, it's negligible.

I believe the main argument *against* having the tb included in the
exception is that it would greatly increase the cyclic nature of
tracebacks and stack frames, which in turn would cause lots of code to
break due to late GC'ing of unclosed files, etc. For example, this
code:

try:
  1/0
except Exception, err:
  pass

will introduce a cycle from err -> traceback -> stack frame -> err,
keeping all locals in the same scope alive until the next GC happens.

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


More information about the Python-3000 mailing list