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