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
语句进行返问,
这种处理方式不仅会带来误解而且可能会引起非常严重的错误。