python中 try、except、finally执行顺序
我们虽然经常用到try...except 作为异常补货,但是其实很少去研究try源码和机制,也许点进去看过,也是看不出个所以然来
class Exception(BaseException):
""" Common base class for all non-exit exceptions. """
def __init__(self, *args, **kwargs): # real signature unknown
pass
继承了BaseException
class BaseException(object):
""" Common base class for all exceptions """
def with_traceback(self, tb): # real signature unknown; restored from __doc__
"""
Exception.with_traceback(tb) --
set self.__traceback__ to tb and return self.
"""
pass def __delattr__(self, *args, **kwargs): # real signature unknown
""" Implement delattr(self, name). """
pass def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass def __init__(self, *args, **kwargs): # real signature unknown
pass
..................
是不是仍然一脸懵逼,同感,哈哈,那还是直接上代码,事实大于雄辩
代码举例转自https://blog.csdn.net/u010159842/article/details/54924940 我觉得这个作者写的很清楚
一:在 try 中 raise一个异常,就立刻转入 except 中执行,在except 中遇到 return 时,就强制转到 finally 中执行, 在 finally 中遇到 return 时就返回,最终函数返回值是finally 返回的
ef test1():
try:
print('to do stuff')
raise Exception('hehe')
print('to return in try')
return 'try'
except Exception:
print('process except')return 'except'
finally:
print('to return in finally')
return 'finally' test1Return = test1()
print('test1Return : ' + test1Return)
#输出: #to do stuff
#process except
#to return in finally
#test1Return : finally
二:这里在 try 中没有抛出异常,因此不会转到 except 中,但是在try 中遇到return时,也会立即强制转到finally中执行,并在finally中返回
def test2():
try:
print('to do stuff')
print('to return in try')
return 'try'
except Exception:
print('process except')
print('to return in except')
return 'except'
finally:
print('to return in finally')
return 'finally' test2Return = test2()
print('test1Return : ' + test2Return)
#输出:
#to do stuff
#to return in try
#to return in finally
#test2Return : finally
test1和test2得到的结论:
无论是在try还是在except中,遇到return时,只要设定了finally语句,就会中断当前的return语句,跳转到finally中执行,如果finally中遇到return语句,就直接返回,不再跳转回try/excpet中被中断的return语句
三
def test3():
i = 0
try:
i += 1
print('i in try : %s'%i)
raise Exception('hehe')
except Exception:
i += 1
print('i in except : %s'%i)
return i
finally:
i += 1
print ('i in finally : %s'%i ) print('test3Return : %s'% test3())
#输出: #i in try : 1
#i in except : 2
#i in finally : 3
#test3Return : 2
def test4():
i = 0
try:
i += 1
return i
finally:
i += 1
print ('i in finally : %s'%i )
print('test4Return : %s' % test4())
#输出
#i in finally : 2
#test4Return : 1
test3和test4得到的结论:
在except和try中遇到return时,会锁定return的值,然后跳转到finally中,如果finally中没有return语句,则finally执行完毕之后仍返回原return点,将之前锁定的值返回(即finally中的动作不影响返回值),如果finally中有return语句,则执行finally中的return语句。
四:test5得到的结论:在一个循环中,最终要跳出循环之前,会先转到finally执行,执行完毕之后才开始下一轮循环
def test5():
for i in range(5):
try:
print('do stuff %s'%i)
raise Exception(i)
except Exception:
print('exception %s'%i)
continue
finally:
print('do finally %s'%i)
test5()
输出 do stuff 0
exception 0
do finally 0
do stuff 1
exception 1
do finally 1
do stuff 2
exception 2
do finally 2
do stuff 3
exception 3
do finally 3
do stuff 4
exception 4
do finally 4
注:
python的错误也是class,所有的错误类型都继承自BaseException,各个类型的错误之间可能会存在继承关系,比如UnicodeError是ValueError的子类,
如果catch语句中同时出现了这两个错误,且UnicodeError在ValueError的后面处理的,那么永远都捕获不到UnicodeError。
python中内置的常用错误类型继承关系:
使用try…excetp捕获错误一个好处是,可以跨层调用,比如main()调用foo(),foo()调用bar(),而错误是在bar中出现的,最后我们只需要在main()中捕获就行。
五:举个工作中的例子
# 首先下面的代码是一段有问题的代码哦,是对try机制了解不清晰
import time
def pushMsg(ss):
try:
res=10/ss # 设置报错点
if res:
return res
except Exception as e:
return False
# 该函数需求是调用pushMsg()函数,默认三次不成功返回,就不再调用
def exceptTest(ss):
cnt = 1
while cnt <= 3:
try:
res = pushMsg(ss)
print("res:",res)
if res:
break # 如果正常返回了,退出循环
except Exception as e:
print(e)
continue # 本意收集
finally:
cnt += 1
time.sleep(1)
print("cnt",cnt)
if cnt > 3:
print("3 times push failed!")
return True # 分两种情况(主要考量except和finall,在两层套用情况下执行顺序,也就是内层函数也用了try ,并且return False)
# 第一种:程序正常走下来,不设置错误 ss传值非零
ss=1
exceptTest(ss)
# 打印执行顺序:只有 res: 10.0,因为内外两层try ,都没有捕获到错误,except和finally 里面都没有执行打印,并且判断res有值就直接break退出循环了 # 第二种情况,置报错 ss传值为零
ss=0
exceptTest(ss) # 打印执行顺序:下面的顺序,先打印了finally里面的内容,再打印了返回值res,但是!为什么except里面的东西没有打印呢!
"""
cnt 2
res: False
cnt 2
res: False
cnt 3
res: False
cnt 4
3 times push failed!
"""
# 总结上面两种情况,无论是有无异常,except里面的东西都没有执行,那外层的try根本没有用呀,这是为什么呢!
# 经过研究,发现内层函数pushMsg(ss),也用了try ,但是他直接return True或者False ,并没有把内层捕获到的错误传到外层,所以外层的try也就捕获不到异常了,y
# 外层函数就会默认没有错误,直接执行finally里面的内容
那么代码就可以这么改
def pushMsg(ss):
try:
res=10/ss # 设置报错点
if res:
return res
except Exception as e:
import traceback
traceback.print_exc()
return False def exceptTest(ss): cnt = 1
while cnt <= 3:
res = pushMsg(ss)
print("res:", res)
if res:
break
else:
cnt += 1
time.sleep(1)
if cnt > 3:
print("3 times push failed!")
return True
python中 try、except、finally执行顺序的更多相关文章
- SQL 中 SELECT 语句的执行顺序
好像自已在书写 SQL 语句时由于不清楚各个关键字的执行顺序, 往往组织的 SQL 语句缺少很好的逻辑, 凭感觉 "拼凑" ( 不好意思, 如果您的 SQL 语句也经常 " ...
- SQLServer2005中查询语句的执行顺序
SQLServer2005中查询语句的执行顺序 --1.from--2.on--3.outer(join)--4.where--5.group by--6.cube|rollup--7.havin ...
- 容易被忽略的事----sql语句中select语句的执行顺序
关于Sql中Select语句的执行顺序,一直很少注意这个问题,对于关键字的使用也很随意,至于效率问题,因为表中的数据量都不是很大,所以也不是很在意. 今天在一次面试的时候自己见到了,感觉没一点的印象, ...
- MySQL-SQL语句中SELECT语句的执行顺序
SELECT语句的执行顺序大家比较少关注,下面将为您详细介绍SQL语句中SELECT语句的执行顺序,供您参考,希望对您能够有所帮助. SELECT语句的执行的逻辑查询处理步骤: (8)SELECT ( ...
- mysql 中sql语句的执行顺序
今天突然想起来,之前面试一个很牛逼的公司(soho)的时候,一个美眉面试官,面试的时候问到了很多之前都没有意识到的问题,回想起来那美眉看着年纪不大,技术那是真666啊.好了说一下人家问的这个有关mys ...
- 在Spring Bean的生命周期中各方法的执行顺序
Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下十种: 通过实现 InitializingBe ...
- java中的代码块执行顺序
/* 代码块:在Java中,使用{}括起来的代码被称为代码块. 根据其位置和声明的不同,可以分为 局部代码块:局部位置,用于限定变量的生命周期. 构造代码块:在类中的成员位置,用{}括起来的代码.每次 ...
- js在html中的加载执行顺序
1.加载顺序:引入标记<script />的出现顺序,依次加载 页面上的Javascript代码是HTML文档的一部分,所以Javascript在页面装载时执行的顺序就是其引入标记< ...
- Unity3D中默认函数的执行顺序
直接用一张图来说明各个默认函数的执行顺序: FixedUpdate以固定的物理时间间隔被调用,不受游戏帧率影响.一个游戏帧可能会调用多次FixedUpdate.比如处理Rigidbody的时候最好用F ...
- Web API中常用Filter的执行顺序举例讲解
在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理.引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想 ...
随机推荐
- 手把手教你吧Python应用到实际开发 不再空谈悟法✍✍✍
手把手教你吧Python应用到实际开发 不再空谈悟法 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问 ...
- SpringCloud-技术专区-Hystrix-使用指南
Maven依赖配置 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId ...
- Vue-cli中的静态资源管理(src/assets和static/的区别)
资源打包 为了回答这个问题,我们需要了解webpack是如何处理静态资源的.在所有的*.vue文件中你所有的templates 和CSS 都被vue-html-loader 和css-loader 查 ...
- LeetCode Array Easy 118. Pascal's Triangle
Description Given a non-negative integer numRows, generate the first numRows of Pascal's triangle. I ...
- mysql莫名报"unknown column ... in 'on clause'"
今天遇见个会诡异的问题 一个web程序本地调试的好好的,结果发布到服务器上程序就报错了,报"unknown column ... in 'on clause'",网上搜了下,说是m ...
- 转帖 新Eclipse安装与配置
Eclipse的官网地址:http://www.eclipse.org/ 我们下载J2EE版本:Eclipse IDE for Java EE Developers 目前最新版本是:Eclipse K ...
- Python 十大装 B 语法解析
Python 是一种代表简单思想的语言,其语法相对简单,很容易上手.不过,如果就此小视 Python 语法的精妙和深邃,那就大错特错了.本文精心筛选了最能展现 Python 语法之精妙的十个知识点,并 ...
- HIVE的Shell操作
1.Hive支持的一些命令 退出使用quit或exit离开交互式外壳. set key = value使用它来设置特定配置变量的值. 这里要注意的一件事是,如果您对变量名拼写错误,cli将不会显示错误 ...
- 73 QT编程入门
0 引言 最近开始在QT下编程,记录一下遇到的问题以及解决方法. 1 安装下载及学习资料 (1)安装下载链接 安装链接: https://blog.csdn.net/qq_23473839/artic ...
- Delphi 实现简易语音发音(基于TTS方式)
uses Comobj; procedure TForm1.Button1Click(Sender: TObject); var voice: OLEVariant; begin voice := C ...