Extract full trace from exception object

Question:

I followed this answer and implemented the following:

def B():
    try:
        raise Exception()
    except Exception as e:
        traceback_ob = e.__traceback__

        import traceback
        traceback_str = ''.join(traceback.format_exception(etype=type(e), value=e, tb=traceback_ob))

        print(traceback_str)

def A():
    B()

A()

The output was:

Traceback (most recent call last):
  File "/path/bespoke_traceback.py", line 3, in B
    raise Exception()
Exception

I need to have the full trace, so including A in the string – how can I achieve this?

To be specific – I need this in a string, not just printed.

Asked By: Omroth

||

Answers:

You can achieve the traceback simply using the logging module no need for other modules:

For same file the exception traceback will be from immediate class. If it is call from different files the logger.exception will print entire traceback

check below example:

import logging
logger = logging.getLogger(__name__)
def B():
    try:
        raise Exception()
    except Exception as e:
        logger.exception("Error",stack_info=True)

def A():
    B()

A()
Answered By: Amit Nanaware

My personal approach: (sorry for using a file but it seemed the only solution)
Sorry if it’s a bit complicated

from threading import Thread
import sys
import os

def B():
    raise Exception()
    
def A():
    B()

def catch_error(f):
    # redirect stderr (where errors are printed) to a temporary file
    # tried StringIO but it only showed part of the exception
    sys.stderr = open('temp', 'w')

    # run it in a thread so that the script doesn't stop after the error
    t = Thread(target=A) 
    t.start()
    t.join()

    # close the file and return stderr back to normal
    sys.stderr.close()
    sys.stderr = sys.__stderr__

    # get error string from the file and then delete it
    s = open('temp', 'r').read()
    os.remove('temp')

    # remove some lines concerning the threading module
    lines = s.split('n')
    [lines.pop(2) for i in range(4)]
    lines.pop(0)

    # join the lines and return
    return 'n'.join(lines)

print(catch_error(A))

Output:

Traceback (most recent call last):
  File "C:UserslenovoAminWorkspacetest.py", line 9, in A
    B()
  File "C:UserslenovoAminWorkspacetest.py", line 6, in B
    raise Exception()
Exception
Answered By: Amin Guermazi

You can combine the format_exception function with the format_stack to get the previous frames:

import traceback

def B():
    try:
        raise Exception("error")
    except Exception as e:
        exception = traceback.format_exception(type(e), value=e, tb=e.__traceback__)
        stack = traceback.format_stack()

        # exception already holds the last (current) frame - we just want to add the previous frames
        exception[1:1] = stack[:-1]

        traceback_str = ''.join(exception)
        print(traceback_str)

def A():
    B()

A()

Will give:

Traceback (most recent call last):
  File "test.py", line 19, in <module>
    A()
  File "test.py", line 17, in A
    B()
  File "test.py", line 5, in B
    raise Exception("error")
Exception: error
Answered By: Tomerikoo
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.