28

I have a bit of code that does some functional exception handling and everything works well, exceptions are raised when I want them to be, but when I'm debugging, the line-traces don't always do quite what I want them to.

Example A:

>>> 3/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

Example B:

>>> try: 3/0
... except Exception as e: raise e
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero

In both of these examples, the exception really occurs in line 1, where we attempt to do 3/0, but in the latter example, we are told it has occurred on line 2, where it is raised.

Is there a way in Python to raise an exception, as if it were another exception, something that would produce the following output:

>>> try: 3/0
... except Exception as e: metaraise(e)
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

2 Answers 2

50

When you re-raise an exception that you caught, such as

except Exception as e: raise e

it resets the stack trace. It's just like re-raising a new exception. What you want is this:

except Exception as e: raise
Sign up to request clarification or add additional context in comments.

4 Comments

And you don't need to store in in a variable in this case.
Except that I need to be storing it in a variable somehow and passing it around to somewhere it will eventually be raised.
@Kevin Dolan: and this is making your code easier to understand and more debuggable, or is it an entry in an obfuscation contest?
It's actually for a decorator abstraction that allows exception swallowing/modification.
6

For reference, the solution is approximately as follows:

def getException():
    return sys.exc_info()

def metaraise(exc_info):
    raise exc_info[0], exc_info[1], exc_info[2]

try: 3/0
except:
    e = getException()
    metaraise(e)

The beautiful part of this is that you can then pass around the variable e and metaraise it somewhere else, even if other exceptions have been encountered along the way.

1 Comment

But then you'll have no information about the trace of the new raise. Any catcher above will be fooled to believe that the exception was raised in the original spot only. The second raiser hides its existence which can be quite confusing in debugging cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.