207 words
1 minute
Find local variables in the traceback for an exception
Find local variables in the traceback for an exception
For sqlite-utils issue #309 I had an error that looked like this:
OverflowError: Python int too large to convert to SQLite INTEGERTraceback (most recent call last): File "/home/sean/.local/bin/sqlite-utils", line 8, in <module> sys.exit(cli()) [...] File "/home/sean/.local/lib/python3.8/site-packages/sqlite_utils/db.py", line 257, in execute return self.conn.execute(sql, parameters)And I wanted to display the values of the sql and parameters variables as part of a custom error message.
It turns out Python exceptions have a e.__traceback__ property which provides access to a traceback - and the local variables in that traceback are avialable on the tb.tb_frame.f_locals dictionary - or if not that one, the tb.tb_next.tb_frame.f_locals property and so on up to the top of the stack.
I wrote this function to find them:
def _find_variables(tb, vars): to_find = list(vars) found = {} for var in to_find: if var in tb.tb_frame.f_locals: vars.remove(var) found[var] = tb.tb_frame.f_locals[var] if vars and tb.tb_next: found.update(_find_variables(tb.tb_next, vars)) return foundUse it like this:
try: db[table].insert_all( docs, pk=pk, batch_size=batch_size, alter=alter, **extra_kwargs ) except Exception as e: # If we can find sql= and params= arguments, show those variables = _find_variables(e.__traceback__, ["sql", "params"]) if "sql" in variables and "params" in variables: raise click.ClickException( "{}\n\nsql = {}\nparams={}".format( str(e), variables["sql"], variables["params"] ) ) else: raiseFull commit add this to sqlite-utils.
Find local variables in the traceback for an exception
https://mranv.pages.dev/posts/find-local-variables-in-the-traceback-for-an-exception/