question about sys.exc_type and sys.exc_value

David Wahler dwahler at gmail.com
Sat Mar 4 23:04:58 EST 2006


John Salerno wrote:
> Here is an exercise from Learning Python that I wrote myself:
>
> import sys
> import traceback
>
> class MyError: pass
>
> def oops():
>      raise MyError()
>
> def safe(func, *args):
>      try:
>          apply(func, args)
>      except:
>          traceback.print_exc()
>          print 'Got', sys.exc_type, sys.exc_value
>
> safe(oops)
>
> And here is the output:
>
> Traceback (most recent call last):
>    File "C:/Python24/oops.py", line 11, in safe
>      apply(func, args)
>    File "C:/Python24/oops.py", line 7, in oops
>      raise MyError()
> MyError: <__main__.MyError instance at 0x00B475A8>
> Got Queue.Empty
>
> Why does it show Queue.Empty as the values for sys.exc_type and
> sys.exc_value? I guess I can somewhat understand Empty, because the
> instance is basically nothing. But why does it say Queue instead of
> MyError? The sample in the book shows "Got hello world", because hello
> is the error name and world is the extra data. But mine doesn't seem to
> work that way. (They are also using a string exception in the book,
> instead of a class.)
>
> Thanks.

Are you using the first edition of "Learning Python"? According to
<http://www.oreilly.com/catalog/lpython/> that was published in 1999,
which puts it right around the end of Python 1.5. I'd strongly suggest
you find a much more recent tutorial, as a lot of python has been
improved and altered since then (sometimes in incompatible ways).

If you look at the sys module's documentation at
<http://docs.python.org/lib/module-sys.html>, you'll notice that
sys.exc_{type,value,traceback} have been deprecated since version 1.5.
That's because there's really no way to use them safely. The reason is
that as global variables, they hold information on the most recent
exception handled _anywhere_ in the program, possibly in another
thread. You should use sys.exc_info() instead, which only returns the
most recent one in the current thread.

If you do a little experimentation, you should notice that your
anomalous result only occurs when you run the code through IDLE -- it
works fine at the command prompt. Also, if you print exc_type and
exc_value first, at the beginning of the except block, it works fine.
The reason for this behavior is that IDLE runs your code in a separate
thread of the same interpreter instance used to run IDLE itself.
Presumably, some code in IDLE's user interface uses a queue to manage
the display, and that results in a Queue.Empty exception being thrown
and caught internally in another thread whenever a line of output is
printed.

The point is that sys.exc_type, sys.exc_value and sys.exc_traceback are
fundamentally unsafe, which is why they've been deprecated for the last
7 years. Incidentally, string exceptions are also deprecated IIRC, so
it's probably best to steer clear of them as well.

Hope this helps,
-- David




More information about the Python-list mailing list