Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python, how do I inspect and then re-raise an exception while maintaining the original call stack?

I've got a situation where I'm catching a specific exception type, inspecting the exception's message to check if it's actually an exception I want to catch, and then re-raising the exception if not:

try:
    # do something exception-prone
except FooException as e:
    if e.message == 'Something I want to handle':
        # handle the exception
    else:
        raise e

This works fine, with one problem. In the case I re-raise the exception, that exception now occurs at the line I re-raised it (i.e. at raise e), rather than at the location the exception originally occurred. This isn't ideal for debugging, where you want to know where the original exception happened.

Thus my question: is there any way to re-raise or otherwise "pass on" an exception after catching it while maintaining the original exception location?

NOTE: In case you are wondering what the actual situation is: I'm dynamically importing some modules using __import__. I'm catching ImportError to gracefully deal with the case that any of these modules do not exist. However, in the case that any of these modules themselves contain an import statement that raises ImportError, I want those "real" (from the point of view of my application) exceptions to be raised -- and at the original location as far as debugging tools are concerned.

like image 533
Ghopper21 Avatar asked Aug 31 '12 05:08

Ghopper21


People also ask

How can an exception be re raised in Python?

Python Language Exceptions Re-raising exceptions In this case, simply use the raise statement with no parameters. But this has the drawback of reducing the exception trace to exactly this raise while the raise without argument retains the original exception trace.

How can you conditionally raise and handle an exception during debugging in Python?

The try-except-finally block is used in Python programs to perform the exception-handling task. Much like that of Java, code that may or may not raise an exception should be placed in the try block.

Can you return after a raise Python?

You can't raise and return , but you could return multiple values, where the first is the same as what you're currently using, and the second indicates if an exception arose return True, sys. exc_info() == (None, None, None) or something similar but better suited to context.


1 Answers

Just do:

raise

instead of raise e. See the tutorial section on raising exceptions, and also the language reference on raise statements:

If no expressions are present, raise re-raises the last exception that was active in the current scope. If no exception is active in the current scope, a TypeError exception is raised indicating that this is an error (if running under IDLE, a Queue.Empty exception is raised instead).

like image 189
lvc Avatar answered Oct 28 '22 23:10

lvc