Skip to content

Instantly share code, notes, and snippets.

@s-hiiragi
Created April 28, 2020 19:20
Show Gist options
  • Save s-hiiragi/002cd6ca84977cd9a2abc432a1922a3e to your computer and use it in GitHub Desktop.
Save s-hiiragi/002cd6ca84977cd9a2abc432a1922a3e to your computer and use it in GitHub Desktop.
Display a traceback with variables in the statement where the error occurred
# coding: utf-8
r"""
Sample output:
C:\Users\USERNAME\repos\python3-exception-with-values>python traceback_with_values.py
Traceback (most recent call last):
File "traceback_with_values.py", line 45, in <module>
print(float(x) + y)
ValueError: could not convert string to float: 'hoge'
Values in the statement:
y=fuga
x=hoge
"""
import sys
import ast
import traceback
import contextlib
def print_exception_with_values(etype, evalue, tb):
traceback.print_exception(etype, evalue, tb)
source = None
lines = ''.join(traceback.format_exception(etype, evalue, tb)[:-1]).splitlines()
for i, line in enumerate(lines):
line = line.strip()
if line.startswith('File'):
if i+1 < len(lines) and lines[i+1].startswith(' '):
source = lines[i+1].strip()
if source is None:
sys.stderr.write('source code is not found in traceback.\n')
return
tree = ast.parse(source)
sys.stderr.write('Values in the statement:\n')
for node in ast.walk(tree):
if isinstance(node, ast.Name):
if isinstance(node.ctx, ast.Load):
if node.id in tb.tb_frame.f_locals:
sys.stderr.write(' {}={}\n'.format(node.id, tb.tb_frame.f_locals[node.id]))
elif node.id in tb.tb_frame.f_globals:
sys.stderr.write(' {}={}\n'.format(node.id, tb.tb_frame.f_globals[node.id]))
sys.excepthook = print_exception_with_values
x = 'hoge'
y = 'fuga'
print(float(x) + y)
@andy-landy
Copy link

Hi, ran into this git googling alternatives for my package. Have a look at this
https://github.com/andy-landy/traceback_with_variables/blob/master/traceback_with_variables/core.py#L19
I guess it does pretty much the same but note that there a standard tools to access all variables without parsing the code tree. I think one can boil the code I mentioned down to a rather small one by eliminating parameters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment