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