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

时间:2016-07-12 01:20:23

标签: 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)

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

1 个答案:

答案 0 :(得分:4)

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
没有参数的

raise意味着您希望将正在处理的异常视为未处理,因此它将继续使用相同的回溯进行传播。

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

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

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