Python如何使用完整的堆栈信息冒泡异常

Jam*_*Lin 1 python

看下面的代码

def ex_string(ex):
    return "Error:{} Traceback:{}".format(ex, traceback.format_exc())

def map_values(listing):
    ...
    obj = listing['value']
    ...

def process_listing(listing):
    try:
        listing = map_values(listing)
    except Exception as ex:
        do_some_handling(listing)
        print ex_string(ex)  # this stack shows actual line inside map_values
        raise ex

def start():
    for listing in listings:
        try:
            process_listing(listing)
            save_listing(listing)
        except Exception as ex:
            error = ex_string(ex)  #this stack shows map_values function only
            log_error(error)
Run Code Online (Sandbox Code Playgroud)

如上所述,当listing不包含'value'元素时,我不知道哪一行导致了问题,我从日志中知道的所有信息都在函数内部的某个地方map_values,如何从首次引发异常的位置获取完整的堆栈跟踪?在这种情况下obj = listing['value']

use*_*ica 5

在子句中使用raise不带参数except来重新引发您正在使用其原始回溯处理的异常:

def process_listing(listing):
    try:
        listing = map_values(listing)
    except Exception as ex:
        do_some_handling(listing)
        print ex_string(ex)
        raise  # no ex
Run Code Online (Sandbox Code Playgroud)

raise不带参数意味着您希望将正在处理的异常视为未处理,因此它会以相同的回溯继续传播。

此处使用raise一个参数意味着您发出信号表明您的异常处理程序遇到了错误,因此 Python 构造了一个新的堆栈跟踪,指向raise异常处理程序中的 。

请注意,raise使用参数在 Python 3 上的行为有所不同,其中异常记录其关联的回溯。在 Python 3 上,raiseraise ex都将保留原始回溯,但raise ex会向该raise ex行的回溯添加额外的记录。

此外,Python 使用一种奇怪的回溯构造系统,其中异常在最初引发时没有堆栈跟踪,并且每次它通过堆栈帧冒泡时,都会将额外的帧记录添加到堆栈跟踪中。(对于具有 1 或 2 个参数的 a 也添加一条记录raise,但不是 0 或 3 个参数,因此与上一段有所不同。)由于此回溯构造系统,回溯不会包含有关异常未包含的帧的任何信息。 t 传播到,并且不寻常的异常处理模式可能会导致回溯看起来与初始 .t 点处的堆栈完全不同raise