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)
Answer from kindall on Stack OverflowSee 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)
Let's create a decently complicated stacktrace, in order to demonstrate that we get the full stacktrace:
def raise_error():
raise RuntimeError('something bad happened!')
def do_something_that_might_error():
raise_error()
Logging the full stacktrace
A best practice is to have a logger set up for your module. It will know the name of the module and be able to change levels (among other attributes, such as handlers)
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
And we can use this logger to get the error:
try:
do_something_that_might_error()
except Exception as error:
logger.exception(error)
Which logs:
ERROR:__main__:something bad happened!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
And so we get the same output as when we have an error:
>>> do_something_that_might_error()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
Getting just the string
If you really just want the string, use the traceback.format_exc function instead, demonstrating logging the string here:
import traceback
try:
do_something_that_might_error()
except Exception as error:
just_the_string = traceback.format_exc()
logger.debug(just_the_string)
Which logs:
DEBUG:__main__:Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
The correct function for tb.something(e) is
''.join(tb.format_exception(None, e, e.__traceback__))
For me @falsePockets' prints only the traceback. I've created this function, which would print the whole exception, including the type and the message:
def error_string(ex: Exception) -> str:
return '\n'.join([
''.join(traceback.format_exception_only(None, ex)).strip(),
''.join(traceback.format_exception(None, ex, ex.__traceback__)).strip()
])
This is how I do it:
>>> import traceback
>>> try:
... int('k')
... except:
... var = traceback.format_exc()
...
>>> print(var)
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'k'
You should however take a look at the traceback documentation, as you might find there more suitable methods, depending to how you want to process your variable afterwards...
sys.exc_info() returns a tuple with three values (type, value, traceback).
- Here type gets the exception type of the Exception being handled
- value is the arguments that are being passed to constructor of exception class
- traceback contains the stack information like where the exception occurred etc.
For Example, In the following program
try:
a = 1/0
except Exception,e:
exc_tuple = sys.exc_info()
Now If we print the tuple the values will be this.
- exc_tuple[0] value will be "ZeroDivisionError"
- exc_tuple[1] value will be "integer division or modulo by zero" (String passed as parameter to the exception class)
- exc_tuple[2] value will be "trackback object at (some memory address)"
The above details can also be fetched by simply printing the exception in string format.
print str(e)
traceback.format_exc() will yield more info if that's what you want.
import traceback
def do_stuff():
raise Exception("test exception")
try:
do_stuff()
except Exception:
print(traceback.format_exc())
This outputs:
Traceback (most recent call last):
File "main.py", line 9, in <module>
do_stuff()
File "main.py", line 5, in do_stuff
raise Exception("test exception")
Exception: test exception
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!")