2

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.

Omroth
  • 759
  • 4
  • 17

3 Answers3

2

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(etype=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 16, in <module>
    A()
  File "test.py", line 14, in A
    B()
  File "test.py", line 5, in B
    raise Exception("error")
Exception: error
Tomerikoo
  • 15,737
  • 15
  • 35
  • 52
0

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:\Users\lenovo\Amin\Workspace\test.py", line 9, in A
    B()
  File "C:\Users\lenovo\Amin\Workspace\test.py", line 6, in B
    raise Exception()
Exception
Amin Guermazi
  • 1,465
  • 7
  • 18
-1

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()
Amit Nanaware
  • 2,974
  • 1
  • 5
  • 18