def FinallyTest():
print("i am starting----")
while True:
try :
print ("I am running")
raise IndexError ("r") #IndexError
except NameError as e:
print ('NameError happended %s',e)
break
finally:
print ("finally executed")
break #finally 句中有 break
FinallyTest()
i am starting---- I am running finally executed
上面的例子中 try 代码块抛出了 IndexError 异常,但在 except 块却没有对应的异常声明。 按常理该异常会向上层抛出,可是程序输出却没有提示任何异常发生, indexError 异常被丢失。 这是什么原因呢?当 try 块中发生异常的时候,如果在 except 语句中找不到对应的异常处理, 异常将会被临时保存起来; 当 finally 执行完毕的时候,临时保存的异常将会冉次被抛出。 但如果 finally 语句中产生了新的异常或者执行了 return 或者 break 语句, 那么临时保存的异常将会被丢失,从而导致异常屏蔽。 这是 finally 使用时需要小心的第一个陷阱。
代码示例
再来看另外一个例子;
def ReturnTest(a):
try:
if a <=0:
raise ValueError("data can not be negative")
else:
return a
except ValueError as e:
print (e)
finally:
print ("The End")
return -1
print (ReturnTest(0))
data can not be negative The End -1
print (ReturnTest(2))
The End -1
思考一下这里程序 RetumTest(0) 和 RetumTest(2) 的返回值是什么?答案是:-1 , -1 。 对于第一个调用 ReturnTest(0) 在抛出 ValueError 异常后直接执行 finally 语句返回值为 -1 , 这点比较容易理解; 那么对于笫二个调用 RetumTest(2) 为什么也返回 -1 呢? 这是因为 a>0 , 会执行 else 分支,何由于存在 finally 语句, 在执行 else 语句的 return a 语句之前会先执行 finally 中的语句, 此时由于 finally 语句中有 return- 1 ,程序直接返回了, 所以永远不会返回 a 对应的值 2 。 此为使用 finally 语句需要注意的第二个陷阱。 在实际应用程序开发过程屮, 并不推荐在 finally 中使用 return 语句进行返问, 这种处理方式不仅会带来误解而且可能会引起非常严重的错误。