Inner exception (with traceback) in Python?
Python 2
It's simple; pass the traceback as the third argument to raise.
import sys
class MyException(Exception): pass
try:
raise TypeError("test")
except TypeError, e:
raise MyException(), None, sys.exc_info()[2]
Always do this when catching one exception and re-raising another.
How to catch and print the full exception traceback without halting/exiting the program?
Some other answer have already pointed out the traceback module.
Please notice that with print_exc
, in some corner cases, you will not obtain what you would expect. In Python 2.x:
import traceback
try:
raise TypeError("Oups!")
except Exception, err:
try:
raise TypeError("Again !?!")
except:
pass
traceback.print_exc()
...will display the traceback of the last exception:
Traceback (most recent call last):
File "e.py", line 7, in <module>
raise TypeError("Again !?!")
TypeError: Again !?!
If you really need to access the original traceback one solution is to cache the exception infos as returned from exc_info
in a local variable and display it using print_exception
:
import traceback
import sys
try:
raise TypeError("Oups!")
except Exception, err:
try:
exc_info = sys.exc_info()
# do you usefull stuff here
# (potentially raising an exception)
try:
raise TypeError("Again !?!")
except:
pass
# end of useful stuff
finally:
# Display the *original* exception
traceback.print_exception(*exc_info)
del exc_info
Producing:
Traceback (most recent call last):
File "t.py", line 6, in <module>
raise TypeError("Oups!")
TypeError: Oups!
Few pitfalls with this though:
From the doc of
sys_info
:Assigning the traceback return value to a local variable in a function that is handling an exception will cause a circular reference. This will prevent anything referenced by a local variable in the same function or by the traceback from being garbage collected. [...] If you do need the traceback, make sure to delete it after use (best done with a try ... finally statement)
but, from the same doc:
Beginning with Python 2.2, such cycles are automatically reclaimed when garbage collection is enabled and they become unreachable, but it remains more efficient to avoid creating cycles.
On the other hand, by allowing you to access the traceback associated with an exception, Python 3 produce a less surprising result:
import traceback
try:
raise TypeError("Oups!")
except Exception as err:
try:
raise TypeError("Again !?!")
except:
pass
traceback.print_tb(err.__traceback__)
... will display:
File "e3.py", line 4, in <module>
raise TypeError("Oups!")
Get exception description and stack trace which caused an exception, all as a string
See the traceback
module, specifically the format_exc()
function. Here.
import traceback
try:
raise ValueError
except ValueError:
tb = traceback.format_exc()
else:
tb = "No error"
finally:
print tb
In Python how can I raise a custom exception and do a trace back as well?
You don't have to "generate" a traceback, Python takes care of this when you raise an exception (custom or builtin).
Python 2.7.3 (default, Feb 27 2014, 19:58:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
pythonrc start
pythonrc done
>>> class MyException(Exception): pass
...
>>> def foo():
... raise MyException("Hey")
...
>>> def bar():
... print "in bar"
... foo()
...
>>> bar()
in bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in bar
File "<stdin>", line 2, in foo
__main__.MyException: Hey
>>>
How to catch inner exception in python?
Apparently first I have to catch the outmost exception
Yes.
I do this and then how do I except the one that follows
You can not except
the one that follows because you're too late. You can examine the context of the exception you did catch, though. Example:
>>> def foo():
... try:
... errorerror
... except NameError:
... 1/0
...
>>> try:
... foo()
... except ZeroDivisionError as err:
... zerr = err
...
>>> zerr.__context__
NameError("name 'errorerror' is not defined")
When cleaning up after the inner exception, there may be other interesting info for you on the outer exception instance. Look at:
- the
__context__
attribute for implicitly chained exceptions - the
__cause__
attribute for explicitly chained exceptions - the
__traceback__
attribute for further context if you need it
See PEP 3134 -- Exception Chaining and Embedded Tracebacks for further details.
How to raise exception in except block without original traceback in python 3.5+
Use raise from None
to suppress earlier exceptions:
try:
can_raise_custom_lib_exception()
except custom_lib_exception as e:
cleanup()
raise myOwnException("my own extra text") from None
7.8. The raise statement
[...]
Exception chaining can be explicitly suppressed by specifyingNone
in thefrom
clause:
Nested causes in nested exceptions in python
In Python 3, you can use the from
keyword to specify an inner exception:
raise ClientException(...) from ioException
You get a traceback that looks like this:
Traceback (most recent call last):
...
IOException: timeout
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
...
ClientException: couldn't read from client
Python variable scope - outer exception variable undefined if used in inner exception
The block beginning
except Exception as msg:
creates the msg
variable at the start of the block, and deletes it at the end of the block. The msg
variable that existed already is in the same scope and has the same name, so it is overwritten and then deleted.
You need to use separate names for your two exceptions if you want to track both, because they are in the same scope.
See https://docs.python.org/3/reference/compound_stmts.html#the-try-statement which says:
When an exception has been assigned using
as target
, it is cleared at the end of the except clause. This is as ifexcept E as N:
foowas translated to
except E as N:
try:
foo
finally:
del N
Related Topics
Trying to Delay a Specific Function for Spawning Enemy After a Certain Amount of Time
Convert a 1D Array to a 2D Array in Numpy
Convert Pandas Series to Dataframe
Understanding Time.Perf_Counter() and Time.Process_Time()
[] and {} VS List() and Dict(), Which Is Better
Command Executed with Paramiko Does Not Produce Any Output
Removing Horizontal Lines in Image (Opencv, Python, Matplotlib)
How to Create an Empty Array and Then Append to It in Numpy
Python: My Function Returns "None" After It Does What I Want It To
How to Log Server Errors on Django Sites
How to Specify "Nullable" Return Type with Type Hints
Selecting Pandas Column by Location
How to Break a Line of Chained Methods in Python
String Comparison Doesn't Seem to Work for Lines Read from a File
Finding Index of Nearest Point in Numpy Arrays of X and Y Coordinates