如何在Python中为异常添加上下文

elm*_*tec 9 python exception

我想为这样的异常添加上下文:

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.
Run Code Online (Sandbox Code Playgroud)

我发现了一种对Python来说异常冗长的方式.有比这更好的方法吗?

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]
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 5

中的第一项ex.args始终是消息——如果有的话。(注意一些例外,例如由 引发的例外assert Falseex.args是一个空元组。)

我不知道比将新元组重新分配给ex.args. (我们不能修改元组,因为元组是不可变的)。

下面的代码与您的类似,不同之处在于它在不使用中间列表的情况下构造元组,处理ex.args为空的情况,并且为了使代码更具可读性,它将样板隐藏在上下文管理器中:

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)
Run Code Online (Sandbox Code Playgroud)

产生一个堆栈跟踪,以此作为最终消息:

ZeroDivisionError: 0: division by zero
Run Code Online (Sandbox Code Playgroud)