The Anatomy of a Traceback
Nir Cohen @ strigo.io
nir0s@github
@thinkops
BEFORE TRACEBACK
...
Traceback (most recent call last):
File "test.py", line 115, in <module>
i = Moose()
File "test.py", line 17, in __init__
self.a_moose_once_bit_my_sister()
File "test.py", line 20, in a_moose_once_bit_my_sister
_mynd_you()
File "test.py", line 110, in _mynd_you
test2.moose_bites_kan_be_pretty_nasti()
File "...test2.py", line 10, in moose_bites_kan_be_pretty_nasti
moose_func(ex)
File "...test2.py", line 14, in moose_func
raise raise_moose(ex)
File "...test2.py", line 18, in raise_moose
raise MooseError(ex)
test2.MooseError: [Errno 2] No such file or directory: \
'certainly_a_non_existing_moose'
The traceback object
try:
raise Exception
except Exception as e:
# py3 specific. In py2 would use:
# _, __, tb = sys.exc_info()
# raise Exception(tb)
raise Exception(e.__traceback__)
...
Traceback (most recent call last):
File "test.py", line 7, in <module>
raise Exception(e.__traceback__)
Exception: <traceback object at 0x7ff5e7f38e08>
Call stack
The call to all functions during execution, where a call to a single function is called a Stack Frame
tb object properties
- `tb_frame` - frame object at this level
- `tb_lasti` - index of last attempted instruction in bytecode
- `tb_lineno` - current line number in Python source code
- `tb_next` - next inner traceback object
The frame object
- `f_back` - next outer frame object
- `f_builtins` - builtins namespace seen by this frame
- `f_code` - code object being executed by this frame
- `f_globals` - global namespace seen by this frame
- `f_lasti` - ...
- `f_lineno` - ...
- `f_locals` - local namespace seen by this frame
- `f_trace` - tracing function for this frame, or `None`
The code object
Too much information.
(See https://goo.gl/lCCxXr)
Use case
Let's say we want to create a logger which will take a parsed/reformatted traceback and ship it for analysis.
from .logger.tracelogger import parse, send
tracelogger.setup(host=..., port=..., format='json')
try:
raise Exception
except Exception as e:
send(parse(traceback.extract_tb(e.__traceback__)))
Replacing the excepthook
def new_excepthook(tpe, value, tb):
# tpe - exception type (e.g. MyException)
# value - the value of the exception
# (e.g. No such file or directory ...)
# tb - the traceback object
do_something_with_exception_type(tpe)
do_something_with_except_value(value)
reformat_traceback(tb)
sys.excepthook = new_excepthook
Extract some info
import traceback
def reformat_traceback(tb):
# Again, a bit different in py2
tb_entries = traceback.extract_tb(e.__traceback__)
for entry in tb_entries:
print((entry.filename, entry.lineno, entry.name, entry.line))
...
('test.py', 140, 'i = Moose()', '<module>')
('test.py', 42, 'self.a_moose_once_bit_my_sister()', '__init__')
('test.py', 45, '_mynd_you()', 'a_moose_once_bit_my_sister')
('test.py', 135, 'test2.moose_bites_kan_be_pretty_nasti()', '_mynd_you')
('.../test2.py', 10, 'moose_func(ex)', 'moose_bites_kan_be_pretty_nasti')
('.../test2.py', 14, 'raise raise_moose(ex)', 'moose_func')
('.../test2.py', 18, 'raise MooseError(ex)', 'raise_moose')
Another use case
Collecting all tracebacks from multiple threads and handling in the main thread
backtrace
Formats tracebacks
Usage (Python)
import backtrace
backtrace.hook(
reverse=False,
align=True,
strip_path=True,
enable_on_envvar_only=False,
on_tty=False,
conservative=False,
styles={})
Usage (Bash)
$ python raise_exception.py 2>&1 | backtrace
...
Traceback (Most recent call last):
115 test.py <module> --> i = Moose()
17 test.py __init__ --> self.a_moose_once_bit_my_sister()
20 test.py a_moose_once_bit_my_sister --> _mynd_you()
110 test.py _mynd_you --> test2.moose_bites_kan_be_pretty_nasti()
...
Project Page
References
- traceback.py source: https://goo.gl/70bGY8
- traceback.c source: https://goo.gl/0AC9Me
- sysmodule source ref: https://goo.gl/URJBb6
- frame object source ref: https://goo.gl/1FR5ZG
- https://late.am/post/2012/03/26/exploring-python-code-objects.html
- Stack vs. Frame: https://goo.gl/abuRHm
- GDB Frames: https://goo.gl/zqc0zR
- https://docs.python.org/3/library/traceback.html
The Anatomy of a Traceback
By Nir Cohen
The Anatomy of a Traceback
- 1,905