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

问题描述 投票:0回答:1

请参阅以下代码

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'元素时,我不知道哪一行导致了问题,我从log中知道的所有内容都在map_values函数内部,如何从首次引发异常的地方获取完整的堆栈跟踪?在这种情况下obj = listing['value']

python
1个回答
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点处堆栈的样子。

© www.soinside.com 2019 - 2024. All rights reserved.