I'm making a couple of functions via exec
, that could possibly error. However when Python errors out it doesn't display the line that the error occurred on.
For example using:
fn_str = '''\
def fn():
raise Exception()
'''
globs = {}
exec(fn_str, globs)
fn = globs['fn']
fn()
Gives us the output:
Traceback (most recent call last):
File "...", line 10, in <module>
fn()
File "<string>", line 2, in fn
Exception
If we however, don't use eval. Then we get the line that the program errored on:
def fn():
raise Exception()
fn()
Traceback (most recent call last):
File "...", line 4, in <module>
fn()
File "...", line 2, in fn
raise Exception()
Exception
I've looked into using the __traceback__
, however I couldn't find a way to add to the traceback under the 'File' line. And so the best I could get was this:
fn_str = '''\
def fn():
try:
raise Exception()
except BaseException as e:
tb = e.__traceback__
if 1 <= tb.tb_lineno <= len(fn_lines):
e.args = ((e.args[0] if e.args else '') + ' - ' + fn_lines[tb.tb_lineno - 1].strip(),)
raise
'''
globs = {'fn_lines': fn_str.split('\n')}
exec(fn_str, globs)
fn = globs['fn']
fn()
Traceback (most recent call last):
File "...", line 16, in <module>
fn()
File "<string>", line 3, in fn
Exception: - raise Exception()
The biggest problem with this is if the eval
calls other code, it becomes confusing where the - raise Exception()
comes from.
Is there a way to make the eval code provide the line that it errored on?