Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get full traceback

How can i get full traceback in the following case, including the calls of func2 and func functions?

import traceback  def func():     try:         raise Exception('Dummy')     except:         traceback.print_exc()  def func2():     func()   func2() 

When i run this, i get:

Traceback (most recent call last):   File "test.py", line 5, in func     raise Exception('Dummy') Exception: Dummy 

traceback.format_stack() is not what i want, as need traceback object to be passed to a third party module.

I am particularly interested in this case:

import logging   def func():     try:         raise Exception('Dummy')     except:         logging.exception("Something awful happened!")   def func2():     func()   func2() 

In this case i am getting:

ERROR:root:Something awful happened! Traceback (most recent call last):   File "test.py", line 9, in func     raise Exception('Dummy') Exception: Dummy 
like image 854
warvariuc Avatar asked Nov 03 '12 15:11

warvariuc


People also ask

What is traceback Python?

In Python, A traceback is a report containing the function calls made in your code at a specific point i.e when you get an error it is recommended that you should trace it backward(traceback). Whenever the code gets an exception, the traceback will give the information about what went wrong in the code.

How do you use TB in Python?

print_tb(tb, limit = None, file = None) : If limit is positive it prints upto limit stack trace entries from traceback object tb. Otherwise, print the last abs(limit) entries. If limit is omitted or None, all entries are printed. If file is omitted or None, the output goes to sys.

How do I fix Python traceback error?

If there is no variable defined with that name you will get a NameError exception. To fix the problem, in Python 2, you can use raw_input() . This returns the string entered by the user and does not attempt to evaluate it. Note that if you were using Python 3, input() behaves the same as raw_input() does in Python 2.


2 Answers

As mechmind answered, the stack trace consists only of frames between the site where the exception was raised and the site of the try block. If you need the full stack trace, apparently you're out of luck.

Except that it's obviously possible to extract the stack entries from top-level to the current frame—traceback.extract_stack manages it just fine. The problem is that the information obtained by traceback.extract_stack comes from direct inspection of stack frames without creating a traceback object at any point, and the logging API requires a traceback object to affect traceback output.

Fortunately, logging doesn't require an actual traceback object, it requires an object that it can pass to the formatting routines of the traceback module. traceback doesn't care either—it only uses two attributes of the traceback, the frame and the line number. So, it should be possible to create a linked list of duck-typed faux-traceback objects and pass it off as the traceback.

import sys  class FauxTb(object):     def __init__(self, tb_frame, tb_lineno, tb_next):         self.tb_frame = tb_frame         self.tb_lineno = tb_lineno         self.tb_next = tb_next  def current_stack(skip=0):     try: 1/0     except ZeroDivisionError:         f = sys.exc_info()[2].tb_frame     for i in xrange(skip + 2):         f = f.f_back     lst = []     while f is not None:         lst.append((f, f.f_lineno))         f = f.f_back     return lst  def extend_traceback(tb, stack):     """Extend traceback with stack info."""     head = tb     for tb_frame, tb_lineno in stack:         head = FauxTb(tb_frame, tb_lineno, head)     return head  def full_exc_info():     """Like sys.exc_info, but includes the full traceback."""     t, v, tb = sys.exc_info()     full_tb = extend_traceback(tb, current_stack(1))     return t, v, full_tb 

With these functions in place, your code only requires a trivial modification:

import logging  def func():     try:         raise Exception('Dummy')     except:         logging.error("Something awful happened!", exc_info=full_exc_info())  def func2():     func()  func2() 

...to give the expected output:

ERROR:root:Something awful happened! Traceback (most recent call last):   File "a.py", line 52, in <module>     func2()   File "a.py", line 49, in func2     func()   File "a.py", line 43, in func     raise Exception('Dummy') Exception: Dummy 

Note that the faux-traceback objects are fully usable for introspection—displaying local variables or as argument to pdb.post_mortem()—because they contain references to real stack frames.

like image 158
user4815162342 Avatar answered Sep 21 '22 21:09

user4815162342


Stack trace is collected when exception bubbles up. So you should print traceback on top of desired stack:

import traceback  def func():     raise Exception('Dummy')  def func2():     func()   try:     func2() except:     traceback.print_exc() 
like image 36
mechmind Avatar answered Sep 21 '22 21:09

mechmind