Wednesday, December 4, 2013

fun with raise

>>> raise ValueError("wrong value")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: wrong value
>>> try:
...    raise ValueError("wrong value")
... except:
...    raise sys.exc_info()
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ValueError

If you want to really re-raise the exact same message, replace sys.exc_info()[0] with the exception instance.

>>> try:
...    raise ValueError("wrong value")
... except Exception as e:
...    raise (e,) + sys.exc_info()[1:]
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ValueError: wrong value

Alas, replacing the traceback object (sys.exc_info()[2]) does not seem to work:

>>> try:
...     json.loads('NOT JSON')
... except:
...     _, _, tb = sys.exc_info()
...
>>> try:
...    1 / 0
... except Exception as e:
...    raise sys.exc_info()[:2], tb
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ZeroDivisionError: <traceback object at 0x02B752B0>

2 comments:

  1. Why not simply,

    try:
    raise ValueError("wrong value")
    except Exception as e:
    raise

    ReplyDelete
    Replies
    1. What you are describing is a useful feature of Python. This blog is focused on pointless and destructive applications of Python semantics. In particular, we are raising the same exception but destroying / manipulating the stack trace so it appears to obfuscate the origin. :-)

      Delete