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.
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()
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
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
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.
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()
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
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