前面的文章已经介绍了try...except...结构和try...except...else...结构,这里介绍try...except...else..finally...结构,即
注意:
try...except...else..finally...结构中的 except 或 else 或 except 和 else 可以没有,即try...finally...也是可以的。
如果try中没有异常,那么except部分将跳过,执行else中的代码(默认try中是没有return语句),最后执行finally的代码;
如果try中出现异常,那么将进入except部分处理异常,最后执行finally的代码。
因此,try中是否出现异常,finally中的代码都会执行。
基于finally语句的这种特性,如果try中的代码程序打开了一些物理资源(文件、数据库链接等)时,由于这些资源必须手动回收(python 垃圾回收机制,只能回收变量、类对象占用的内存,而无法自动完成类似关闭文件、数据库链接等这些工作),所以可以把回收这些物理资源的工作放在finally中。
例:
try:
print("open file")
f = open("test1.txt", "w")
f.write("hello world!")
finally: # 无论try中写文件的过程中是否有异常,finally中关闭文件的操作一定会执行
print("close file")
f.close()
print("continue...")
注意:
finally中一般不使用return语句,如果finally中含有return语句,可能会导致一些问题。
例1:
def test():
try:
print(1)
return 1
except:
print(2)
finally:
print(3)
return 3
print('continue...')
print(test())
执行结果:
continue...
1
3
3
分析:
在try代码块return之前,会执行finally中的语句,导致try中的return被忽略了,最终返回的值是finally中return的值。
例2:
def test():
try:
print(1)
raise ValueError()
except IndexError:
print(2)
finally:
print(3)
return 3
print('continue...')
print(test())
执行结果:
continue...
1
3
3
分析:
try中抛出的异常类型是ValueError,而except中只能捕获IndexError类型的,try中抛出的异常没有被捕获到,所以except中的语句没有被执行,但finally还是会执行,最终函数返回了finally中的返回值3。
理论上try中抛出的异常没有被捕获到,当finally执行完毕后,应该被再次抛出,但是这里的finally里执行了return,因此就导致了异常被丢失。
把finally中的return语句去掉后,可以得到理论上的执行结果:
continue...
1
3
Traceback (most recent call last):
File "E:/pycharm/python project/main.py", line 11, in <module>
print(test())
File "E:/pycharm/python project/main.py", line 4, in test
raise ValueError()
ValueError
参考资料:
http://c.biancheng.net/view/2316.html
https://mp.weixin.qq.com/s/6jBvyl1YoVBRyVQCdC67Sg