Search code examples
pythonexceptiontraceback

Formatting an exception in python to include all but the last 'n' traceback frames


Assume you had a setup like this:

def a():
    b()

def b():
    c()

def c():
    d()

def d():
    e()

Attempting to call a() would result in the following traceback:

Traceback (most recent call last):
  File "<pyshell#181>", line 1, in <module>
    a()
  File "<pyshell#87>", line 2, in a
    b()
  File "<pyshell#90>", line 2, in b
    c()
  File "<pyshell#93>", line 2, in c
    d()
  File "<pyshell#96>", line 2, in d
    e()
NameError: name 'e' is not defined

Is there any way to format the exception so that it only includes the last n frames in the traceback? For example, if n = 2, the traceback would look like this:

Traceback (most recent call last):
  File "<pyshell#93>", line 2, in c
    d()
  File "<pyshell#96>", line 2, in d
    e()
NameError: name 'e' is not defined

I've tinkered with it for a little bit and can't figure out a way to do it.


Solution

  • Starting from Python 3.5, functions from the traceback module support negative limits (the original proposal was inspired by your question and approved by Guido):

    import traceback
    
    n = 2
    
    try:
        a()
    except:
        traceback.print_exc(limit=-n) # `n` last traceback entries
    

    outputs

    Traceback (most recent call last):
      File "/home/vaultah/test.py", line 8, in c
        d()
      File "/home/vaultah/test.py", line 11, in d
        e()
    NameError: name 'e' is not defined
    

    You can replicate this behavior even if you use older Python

    import sys, traceback
    
    n = 2
    
    try:
        a()
    except:
        ex = traceback.format_exception(*sys.exc_info())
        sys.stderr.write(''.join([ex[0]] + ex[-n-1:]))
        # or print(*[ex[0]] + ex[-n-1:], sep='', end='', file=sys.stderr)
    

    The output will be exactly the same.