finally
finally
try:
f = open("/tmp/output", "w")
f.write("hello")
#raise Exception("something wrong")
finally:
print("closing file")
f.close()
代码
不论try中写文件的过程中是否有异常,finally中关闭文件的操作一定会执行。由于finally的这个特性,finally经常被用来做一些清理工作。
我们再来看下面的例子
def func1():
try:
return
finally:
return def func2():
try:
raise ValueError()
except:
return
finally:
return print(func1())
print(func2())
例子
这个例子中 func1() 和 func2() 返回什么呢?
答案是 func1() 返回2, func2() 返回3。为什么是这样的呢?我们先来看一段Python官网上对于finally的解释:
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. When an exception has occurred in the try clause and has not been handled by an except clause (or it has occurred in a except or else clause), it is re-raised after the finally clause has been executed. The finally clause is also executed “on the way out” when any other clause of the try statement is left via a break, continue or return statement.
重点部分用粗体标出了,翻成中文就是try块中包含break、continue或者return语句的,在离开try块之前,finally中的语句也会被执行。
所以在上面的例子中,func1() 中,在try块return之前,会执行finally中的语句,try中的return被忽略了,最终返回的值是finally中return的值。func2() 中,try块中抛出异常,被except捕获,在except块return之前,执行finally中的语句,except中的return被忽略,最终返回的值是finally中return的值。
我们在上面的例子中加入print语句,可以更清楚地看到过程
def func1():
try:
print 'in func1 try: try statement, will return 1'
return
finally:
print 'in func1 finally: try statement, will return 2'
return def func2():
try:
print 'in func2 try: raise error'
raise ValueError()
except:
print 'in func2 except: caught error, will return 1!'
return
finally:
print 'in func2 finally: will return 3'
return print func1()
print func2()
加print代码
上面的代码输出
in func1 try: try statement, will return
in func1 finally: try statement, will return in func2 try: raise error
in func2 except: caught error, will return !
in func2 finally: will return
结果
我们对上面的func2做一些修改,如下
def func2():
try:
print 'in func2 try: raise error'
raise ValueError()
except IndexError:
print 'in func2 except: caught error, will return 1!'
return
finally:
print 'in func2 finally: will return 3'
return print func2()
修改代码
输出如下
in func2 try: raise error
in func2 finally: will return
结果
try中抛出的异常是ValueError类型的,而except中定位的是IndexError类型的,try中抛出的异常没有被捕获到,所以except中的语句没有被执行,但不论异常有没有被捕获,finally还是会执行,最终函数返回了finally中的返回值3。
这里还可以看到另外一个问题。try中抛出的异常没有被捕获到,按理说当finally执行完毕后,应该被再次抛出,但finally里执行了return,导致异常被丢失。
可以看到在finally中使用return会导致很多问题。实际应用中,不推荐在finally中使用return返回。
随机推荐
- MongoDB基操
基本概念 database 数据库 包含多个collection collection 集合 包含多个文档document(类JSON对象) document 文档 一个文档对象中包含多个key-va ...
- 使用snmp4j实现Snmp功能(三)
相关链接:Snmp学习笔记使用snmp4j实现Snmp功能(一)使用snmp4j实现Snmp功能(二)使用snmp4j实现Snmp功能(三) 前两篇文章讲了如何使用Snmp4j实现Set.Get(使用 ...
- The Shortest Path in Nya Graph HDU - 4725
Problem Description This is a very easy problem, your task is just calculate el camino mas corto en ...
- 【题解】最大公约数之和 V3 51nod 1237 杜教筛
题目传送门 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1237 数学题真是做的又爽又痛苦,爽在于只要推出来公式基本上就 ...
- bzoj 4900 [CTSC2017]密钥 模拟+乱搞
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4900 #include<cstring> #include<cmath&g ...
- linux和windows多线程的异同
linux多线程及线程同步和windows的多线程之间的异同 并不是所有的程序都必须采用多线程,有时候采用多线程性能还不如单线程.采用多线程的好处如下: (1)多线程之间采用相同的地址空间,共享大部分 ...
- 爬虫服务集群处理nginx返回504
最近在对爬虫服务做分布式服务的时候总是遇到服务器返回504,搞了两天才发现原来是nginx中有对超时的设置参数,自己都是用默认的,然而客户端的等待时间超过了nginx默认的超时设置 修改 keepal ...
- javascript实现购物车思路
/* 思路: 第一步:获取所要操作的节点对象 第二步:当页面加载完后,需要计算本地cookie存了多少[个]商品,把个数赋值给count 第三步:为每一个商品对应的添加购物车按钮绑定一个点击事件onc ...
- shell脚本实现轮询查看进程是否结束
功能需求: 一个shell脚本,为了使用多进程,启动十几个后台运行的程序,为了防止脚本比后台进程提前结束造成不可预估的影响,现要判断是否多个后台执行的已知进程已经结束,并在所有进程结束后做出相应操作. ...
- java 反射和new的区别
关于java 反射和new的区别,在这里我不做多讲,因为网上有大把资料,描述得很详细. 今天我只讲一点,为什么要用反射?直接用new不行么?干嘛弄得那么麻烦! 1.基本上效果差不多,但是new对象,无 ...