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
Answer from volting on Stack Overflow
🌐
Python
docs.python.org › 3 › library › traceback.html
traceback — Print or retrieve a stack traceback
This module provides a standard interface to extract, format and print stack traces of Python programs. It is more flexible than the interpreter’s default traceback display, and therefore makes it possible to configure certain aspects of the ...
🌐
Real Python
realpython.com › python-traceback
Understanding the Python Traceback – Real Python
July 29, 2019 - When your program results in an exception, Python will print the current traceback to help you know what went wrong. Below is an example to illustrate this situation: ... Here, greet() gets called with the parameter someone. However, in greet(), that variable name is not used.
Top answer
1 of 16
1534

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
2 of 16
880

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!")
Top answer
1 of 3
17

Use the traceback module. For Python 3.10 and up, you can just write

for exc in errors:
    traceback.print_exception(exc)

On previous versions, traceback.print_exception only supports the old type/value/traceback format, so you'll have to extract type(exc) and exc.__traceback__ yourself:

for exc in errors:
    traceback.print_exception(type(exc), exc, exc.__traceback__)

Also, be aware that Python has a very strange way of building tracebacks, where an entry for a stack frame is added to the traceback when an exception propagates into that stack frame, rather than building the traceback all at once when the exception is created or raised.

This means that an exception's traceback stops at the point where it stopped propagating. When your the_method catches an exception, the exception's traceback will stop at the_method.

2 of 3
1

Exceptions have attributes, just like other objects in Python. You may want to explore the attributes of your exceptions. Consider the following example:

>>> try:
    import some_junk_that_doesnt_exist
except Exception as error:
    print(dir(error))


['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', '_not_found', 'args', 'msg', 'name', 'path', 'with_traceback']

This means that for each exception in your list, you can access the exception's attribute. Thus, you can do the following:

for e in err:
    print(e.args)
    print(e.name)
    print(e.msg)

One thing that occurs to me, though, is that the following line shouldn't really append more than one exception to your errors list:

except Exception as e:
     errors.append(e)

Someone else will know better than I would, but isn't Exception always going to be one thing here (unless you're capturing multiple specific exceptions)?

🌐
Python.org
discuss.python.org › python help
Different behavior of `BaseException.with_traceback` in Python 3.11 vs 3.10? - Python Help - Discussions on Python.org
May 4, 2023 - Here is a short code example. I’m chaining function calls f, g, and eventually h where an exception is being raised. The traceback, as expected, shows the call to f (in ", line 1, in File " ", line 1, in f File " ", line 1, in g File "
🌐
Coursera
coursera.org › tutorials › how to print, read, and format a python traceback
How to Print, Read, and Format a Python Traceback | Coursera
March 10, 2023 - Python provides a traceback when an exception is raised. You can extract, format, and print stack traces with the Python traceback module.
🌐
GeeksforGeeks
geeksforgeeks.org › traceback-in-python
Traceback in Python - GeeksforGeeks
August 1, 2020 - Traceback is a python module that provides a standard interface to extract, format and print stack traces of a python program. When it prints the stack trace it exactly mimics the behaviour of a python interpreter.
Find elsewhere
🌐
DEV Community
dev.to › martinheinz › creating-beautiful-tracebacks-with-pythons-exceptions-hooks-4869
Creating Beautiful Tracebacks with Python's Exception Hooks - DEV Community
February 2, 2022 - We use traceback (tb) object to access the traceback frame which contains data describing where the exception occurred - that is - filename (f_code.co_filename), function/module name (f_code.co_name) and line number (tb_lineno). Apart from that, we also print information about exception itself using the exc_type and exc_value variables. With this hook in place, we can invoke a function that raises some exception and we will receive the following output:
🌐
Python Module of the Week
pymotw.com › 2 › traceback
traceback – Extract, format, and print exceptions and stack traces. - Python Module of the Week
The format functions return a list of strings with messages formatted to be printed. There are shorthand functions for printing the formatted values, as well. Although the functions in traceback mimic the behavior of the interactive interpreter by default, they also are useful for handling exceptions in situations where dumping the full stack trace to stderr is not desirable.
🌐
MachineLearningMastery
machinelearningmastery.com › home › blog › understanding traceback in python
Understanding Traceback in Python - MachineLearningMastery.com
June 21, 2022 - If you run this program using the Python interpreter, you will see this: The lines starting with “Traceback (most recent call last):” are the traceback. It is the stack of your program at the time when your program encountered the exception. In ...
🌐
GitHub
gist.github.com › rpdelaney › 4e5cfb2d05d4898ae8f147c4cc02f481
Transforming python exceptions while preserving the traceback · GitHub
>>> def do_foo(): >>> pass >>> >>> >>> def do_bar(): >>> pass >>> >>> >>> dispatch_table = { >>> 'foo': do_foo, >>> 'bar': do_bar, >>> } >>> >>> key = 'baz' >>> result = dispatch_table[key] Traceback (most recent call last): File "foo.py", line 15, in <module> result = dispatch_table[key] KeyError: 'baz' Presuming that 'baz' was the user's input, we want the user to understand that they have passed in an unsupported/nonexistent command. A KeyError doesn't explain that: it only says a key wasn't found in a dictionary. (And if the user isn't experienced in python, it doesn't even say that!)
🌐
W3Schools
w3schools.com › python › ref_module_traceback.asp
Python traceback Module
Python Examples Python Compiler Python Exercises Python Quiz Python Challenges Python Practice Problems Python Server Python Syllabus Python Study Plan Python Interview Q&A Python Training ... import traceback try: result = 10 / 0 except ZeroDivisionError: tb = traceback.format_exc() print('Exception caught and formatted') Try it Yourself »
🌐
FavTutor
favtutor.com › blogs › python-traceback
Python Traceback: How to Read? & Error Types? (with Example)
April 12, 2023 - To interpret the traceback in Python, first, we will check the top for the exception type and message. Then, we will look at the traceback entries after that. These are the active function calls with line number and filename.
🌐
Python
docs.python.org › 3 › builtins › exceptions.html
Built-in Exceptions — Python 3.14.7 documentation
Some built-in exceptions (like ... a single string giving an error message. ... This method sets tb as the new traceback for the exception and returns the exception object....
🌐
Real Python
realpython.com › ref › stdlib › traceback
traceback | Python Standard Library – Real Python
>>> import traceback >>> try: ... # Open a non-existing file ... with open("file.txt", mode="r", encoding="utf-8") as file: ... content = file.read() ... except FileNotFoundError as e: ... with open("error.log", "w") as log_file: ... log_file.write(traceback.format_exc()) ... By writing the stack trace to error.log, you ensure that detailed error information is available for future review—making debugging and troubleshooting much easier. This technique provides a reliable way to capture detailed error information for later debugging and troubleshooting. ... In this step-by-step tutorial, you'll learn how to read and understand the information you can get from a Python traceback.
🌐
Python Morsels
pythonmorsels.com › reading-tracebacks-in-python
Deciphering Python's Traceback (most recent call last) - Python Morsels
January 3, 2022 - In general, the deepest stack frame in our traceback won't always be our code (that is code we wrote). It could be code from some other module besides our own. So sometimes you'll need to read other frames in your call stack above that bottom one. ... That error message means Python tried to use the + operator between a string and an integer, and that's not allowed.
Top answer
1 of 7
137

The answer to this question depends on the version of Python you're using.

In Python 3

It's simple: exceptions come equipped with a __traceback__ attribute that contains the traceback. This attribute is also writable, and can be conveniently set using the with_traceback method of exceptions:

raise Exception("foo occurred").with_traceback(tracebackobj)

These features are minimally described as part of the raise documentation.

All credit for this part of the answer should go to Vyctor, who first posted this information. I'm including it here only because this answer is stuck at the top, and Python 3 is becoming more common.

In Python 2

It's annoyingly complex. The trouble with tracebacks is that they have references to stack frames, and stack frames have references to the tracebacks that have references to stack frames that have references to... you get the idea. This causes problems for the garbage collector. (Thanks to ecatmur for first pointing this out.)

The nice way of solving this would be to surgically break the cycle after leaving the except clause, which is what Python 3 does. The Python 2 solution is much uglier: you are provided with an ad-hoc function,sys.exc_info(), which only works inside the except clause. It returns a tuple containing the exception, the exception type, and the traceback for whatever exception is currently being handled.

So if you are inside the except clause, you can use the output of sys.exc_info() along with the traceback module to do various useful things:

>>> import sys, traceback
>>> def raise_exception():
...     try:
...         raise Exception
...     except Exception:
...         ex_type, ex, tb = sys.exc_info()
...         traceback.print_tb(tb)
...     finally:
...         del tb
... 
>>> raise_exception()
  File "<stdin>", line 3, in raise_exception

But as your edit indicates, you're trying to get the traceback that would have been printed if your exception had not been handled, after it has already been handled. That's a much harder question. Unfortunately, sys.exc_info returns (None, None, None) when no exception is being handled. Other related sys attributes don't help either. sys.exc_traceback is deprecated and undefined when no exception is being handled; sys.last_traceback seems perfect, but it appears only to be defined during interactive sessions.

If you can control how the exception is raised, you might be able to use inspect and a custom exception to store some of the information. But I'm not entirely sure how that would work.

To tell the truth, catching and returning an exception is kind of an unusual thing to do. This might be a sign that you need to refactor anyway.

2 of 7
116

Since Python 3.0[PEP 3109] the built in class Exception has a __traceback__ attribute which contains a traceback object (with Python 3.2.3):

>>> try:
...     raise Exception()
... except Exception as e:
...     tb = e.__traceback__
...
>>> tb
<traceback object at 0x00000000022A9208>

The problem is that after Googling __traceback__ for a while I found only few articles but none of them describes whether or why you should (not) use __traceback__.

However, the Python 3 documentation for raise says that:

A traceback object is normally created automatically when an exception is raised and attached to it as the __traceback__ attribute, which is writable.

So I assume it's meant to be used.