>>> from env_helper import info; info()
页面更新时间: 2024-01-20 22:03:05
运行环境:
Linux发行版本: Debian GNU/Linux 12 (bookworm)
操作系统内核: Linux-6.1.0-17-amd64-x86_64-with-glibc2.36
Python版本: 3.11.2
3.7. 避免finally中可能发生的陷阱¶
无论 try
语句中是否有异常抛出, finally
语句总会被执行。
由于这个特性, finally
语句经
常被用来做一些清理工作,如打开一个文件,抛出异常后在 finally
语句中对文件句柄进行关闭等。 但使用 finally
时,也要特别小心一些陷阱。先来看以下例子:
3.7.1. finally 中的 break
¶
>>>
>>> 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
使用时需要小心的第一个陷阱。
3.7.2. 第二个例子¶
再来看 另外一个例子;
>>> 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))
>>> print (ReturnTest(2))
data can not be negative
The End
-1
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
语句进行返问,这种处理方式不仅会带来误解而且可能会引 起非常严重的错误。