How can I add context to an exception in Python
exception, python
Solution
The first item in `ex.args` is always the message -- if there is any. (Note for some exceptions, such as the one raised by `assert False`, `ex.args` is an empty tuple.)
I don't know of a cleaner way to modify the message than reassigning a new tuple to `ex.args`. (We can't modify the tuple since tuples are immutable).
The code below is similar to yours, except it constructs the tuple without using an intermediate list, it handles the case when `ex.args` is empty, and to make the code more readable, it hides the boilerplate inside a context manager:
import contextlib
def process(val):
with context(val):
do_something(val)
def do_something(val):
# assert False
return 1/val
@contextlib.contextmanager
def context(msg):
try:
yield
except Exception as ex:
msg = '{}: {}'.format(msg, ex.args[0]) if ex.args else str(msg)
ex.args = (msg,) + ex.args[1:]
raise
process(0)
yields a stack trace with this as the final message:
ZeroDivisionError: 0: division by zero
Problem
I would like to add context to an exception like this: ``` def process(vals): for key in vals: try: do_something(vals[key]) except Exception as ex: # base class. Not sure what to expect. raise # with context regarding the key that was being processed. ``` I found a way that is uncharacteristically long winded for Python. Is there a better way than this? ``` try: do_something(vals[key]) except Exception as ex: args = list(ex.args) if len(args) > 1: args[0] = "{}: {}".format(key, args[0]) ex.args = tuple(args) raise # Will re-trhow ValueError with new args[0] ```