转载自 https://www.cnblogs.com/JohnABC/p/4065437.html

学习python或者其他有异常控制的编程语 言, 大家很有可能说try except finally(try catch finally)的执行很简单,无非就是有异常的话执行except, finally无论是否有异常都会执行, 大致上原则是这样, 但是如果涉及到更加详细的复杂的路径,加上return 语句,就没有那么简单了。

1. 没有return 语句的情况

print 'this is a test of code path in try...except...else...finally'
print '************************************************************' def exceptTest():
try:
print 'doing some work, and maybe exception will be raised'
raise IndexError('index error')
#print 'after exception raise'
#return 0 except KeyError, e:
print 'in KeyError except'
print e
#return 1
except IndexError, e:
print 'in IndexError except'
print e
#return 2
except ZeroDivisionError, e:
print 'in ZeroDivisionError'
print e
#return 3
else:
print 'no exception'
#return 4
finally:
print 'in finally'
#return 5 resultCode = exceptTest()
print resultCode
上面的代码是一直要使用的代码,只不过暂时不用的代码被comment了。

有异常发生,并且捕获异常,最后在finally进行处理,上面代码的输出:

this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
in IndexError except
index error
in finally
None

然后我们逐渐给上面代码各个情况添加return 语句, 查看添加return 语句后的代码执行效果。

2. 添加return 语句的情况

print 'this is a test of code path in try...except...else...finally'
print '************************************************************' def exceptTest():
try:
print 'doing some work, and maybe exception will be raised'
raise IndexError('index error')
print 'after exception raise'
return 0 except KeyError, e:
print 'in KeyError except'
print e
return 1
except IndexError, e:
print 'in IndexError except'
print e
return 2
except ZeroDivisionError, e:
print 'in ZeroDivisionError'
print e
return 3
else:
print 'no exception'
return 4
finally:
print 'in finally'
return 5 resultCode = exceptTest()
print resultCode

这个时候所有的分支都存在return 语句,并且会引发异常, 看一下输出:

this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
in IndexError except
index error
in finally
5

异常发生后,raise语句以后的不再执行,然后到了捕获异常语句, 但是捕获异常模块有个return , 是不是这个时候就不再继续执行直接返回呢?但是这是跟 finally语句必然执行是相冲突的, 可以在结果中看到finally实际上执行了,并且返回值是5,在 finally de 的返回值。

然后,我们在看看把finally 的返回值注释掉,看看返回值是多少?

代码如下:

print 'this is a test of code path in try...except...else...finally'
print '************************************************************' def exceptTest():
try:
print 'doing some work, and maybe exception will be raised'
raise IndexError('index error')
print 'after exception raise'
return 0 except KeyError, e:
print 'in KeyError except'
print e
return 1
except IndexError, e:
print 'in IndexError except'
print e
return 2
except ZeroDivisionError, e:
print 'in ZeroDivisionError'
print e
return 3
else:
print 'no exception'
return 4
finally:
print 'in finally'
#return 5 resultCode = exceptTest()
print resultCode

这个时候的程序输出:

this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
in IndexError except
index error
in finally
2

返回值变为2, 这个时候有点疑惑了, 先不用解释问题,我们继续看其他的情况。

3. 没有异常发生且try语句块没有return

代码如下:

print 'this is a test of code path in try...except...else...finally'
print '************************************************************' def exceptTest():
try:
print 'doing some work, and maybe exception will be raised'
#raise IndexError('index error')
print 'after exception raise'
#return 0 except KeyError, e:
print 'in KeyError except'
print e
return 1
except IndexError, e:
print 'in IndexError except'
print e
return 2
except ZeroDivisionError, e:
print 'in ZeroDivisionError'
print e
return 3
else:
print 'no exception'
return 4
finally:
print 'in finally'
return 5 resultCode = exceptTest()
print resultCode

这个时候的代码输出:

this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
after exception raise
no exception
in finally
5

这里验证了如果没有异常那么else语句是执行的,并且finally语句执行,然后返回finally语句的return 5

但是,当try语句块里存在return语句是什么情况呢?

4. 没有异常发生且try语句块 存在return语句

print 'this is a test of code path in try...except...else...finally'
print '************************************************************' def exceptTest():
try:
print 'doing some work, and maybe exception will be raised'
#raise IndexError('index error')
print 'after exception raise'
return 0 except KeyError, e:
print 'in KeyError except'
print e
return 1
except IndexError, e:
print 'in IndexError except'
print e
return 2
except ZeroDivisionError, e:
print 'in ZeroDivisionError'
print e
return 3
else:
print 'no exception'
return 4
finally:
print 'in finally'
return 5 resultCode = exceptTest()
print resultCode

执行结果:

this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
after exception raise
in finally
5

这里else没有执行,和我们对于书本知识有冲突了, finally语句执行并返回5.

分析: 这里因为没有发生异常, 所以会执行到try块中的return 语句,但是finally又必须执行,所以执行try中return 之前去执行了finally语句,并且可以认为,finally语句修改了最后返回的值,将try中的返回值修改为5并最终返回,所以else语句并没有 得到执行。

5. 有异常发生并且finally 没有return 语句

print 'this is a test of code path in try...except...else...finally'
print '************************************************************' def exceptTest():
try:
print 'doing some work, and maybe exception will be raised'
raise IndexError('index error')
print 'after exception raise'
return 0 except KeyError, e:
print 'in KeyError except'
print e
return 1
except IndexError, e:
print 'in IndexError except'
print e
return 2
except ZeroDivisionError, e:
print 'in ZeroDivisionError'
print e
return 3
else:
print 'no exception'
return 4
finally:
print 'in finally'
#return 5 resultCode = exceptTest()
print resultCode

执行结果:

this is a test of code path in try...except...else...finally
************************************************************
doing some work, and maybe exception will be raised
in IndexError except
index error
in finally
2

因为有异常发生,所以try中的return语句肯定是执行不到的,然后在捕获到的except中进行执行,并且except中存在return 语句,那么是不是就直接返回? 因为finally 语句是必须要执行的,所以这里的return语句需要先暂且放下,进入finally进行执行,然后finnaly执行完以后再返回到 except中进行执行。

看到这里,我们貌似找到了一些规律

1. 如果没有异常发生, try中有return 语句, 这个时候else块中的代码是没有办法执行到的, 但是finally语句中如果有return 语句会修改最终的返回值, 我个人理解的是try中return 语句先将要返回的值放在某个 CPU寄存器,然后运行finally语句的时候修改了这个寄存器的值,最后在返回到try中的return语句返回修改后的值。

2. 如果没有异常发生, try中没有return语句,那么else块的代码是执行的,但是如果else中有return, 那么也要先执行finally的代码, 返回值的修改与上面一条一致。

3. 如果有异常发生,try中的return语句肯定是执行不到, 在捕获异常的 except语句中,如果存在return语句,那么也要先执行finally的代码,finally里面的代码会修改最终的返回值,然后在从 except 块的retrun 语句返回最终修改的返回值, 和第一条一致。

转自:http://www.2cto.com/kf/201405/304975.html

Python异常捕捉try except else finally有return时执行顺序探究的更多相关文章

  1. python 异常捕捉与异常处理

    简介 在实际开发中,为了防止异常界面直接被用户看到,往往我们会采用捕捉异常的方式来进一步处理异常. 异常捕捉 如下代码由于下标越界会导致异常 data = range(10) print(data[1 ...

  2. python 异常捕捉总结

    Process finished with exit code -1 错误 执行代码 pycharm2020.1中手动中断程序,可是却捕捉不了中断异常,并且输出Process finished wit ...

  3. python异常捕捉以及处理

    看标题觉得高大上,好像能处理所有的异常.但是,事实是只能按照字面的意思来理解这一段话. 众所周知写代码哪有不出bug的? 那么出现了bug 我们不想让程序因为bug的存在而退出.那么要怎么做呢? 今天 ...

  4. Python异常捕捉的一个小问题

    问题: names = ['taotao','songwenjing','liu','li']I = iter(names)while True: try: s = next(I) except Ex ...

  5. python nose测试框架全面介绍十二 ----用例执行顺序打乱

    在实际执行自动化测试时,发现我们的用例在使用同一个资源的操作时,用例的执行顺序对测试结果有影响,在手工测试时是完全没法覆盖的. 但每一次都是按用例名字来执行,怎么打乱来执行的. 在网上看到一个有意思的 ...

  6. python单元测试框架-unittest(三)之用例执行顺序

    执行顺序规则: 测试类或测试方法的数字与字母顺序0~9,A-Z 执行如下脚本,理解用例执行顺序 #coding=utf-8 import unittest class Test1(unittest.T ...

  7. python nose 自写插件打乱class类中用例执行顺序,但将test_a和test_z排除

    在使用nose时,有这样一个需求,用例执行打乱,但部分用例因场景原因必须先执行,这类用例在写用例时人为的加上了test_a或test_z字样 网上找了一圈,都没找到合适的方法,只有自己写插件了 已写完 ...

  8. python 异常

    引用一段来自菜鸟教程的文章:http://www.runoob.com/python/python-exceptions.html Python 异常处理 python提供了两个非常重要的功能来处理p ...

  9. #21 Python异常

    前言 运行程序时经常遇到各种错误,例如:ImportError(导入模块错误).IndexError(索引错误).NameError(变量错误).SyntaxError(语法错误).Indentati ...

随机推荐

  1. 【bzoj2351】[BeiJing2011]Matrix 二维Hash

    题目描述 给定一个M行N列的01矩阵,以及Q个A行B列的01矩阵,你需要求出这Q个矩阵哪些在原矩阵中出现过.所谓01矩阵,就是矩阵中所有元素不是0就是1. 输入 输入文件的第一行为M.N.A.B,参见 ...

  2. Java Servlet异步处理、非阻塞I/O和文件上传

    异步处理 应用服务器中的 web容器通常对各个客户端情求分别使用一个服务器线程.在工作负载很繁重的情况下,容器常要大量线程来为所有客户端请求服务.可扩展性限制包括内存用尽,或容器线程池耗尽.为了创建可 ...

  3. Java 读取Excel2007 jar包冲突的问题(org.apache.poi.POIXMLException: java.lang.reflect.InvocationTargetException)

    1.jar包冲突报错问题 2.使用的jar包,以及重复jar包 3.删除重复jar包

  4. BZOJ4719 NOIP2016天天爱跑步(线段树合并)

    线段树合并的话这个noip最难题就是个裸题了. 注意merge最后return x,以及如果需要区间查询的话这里还需要up,无数次死于这里. #include<iostream> #inc ...

  5. 洛谷P1345 [USACO5.4]奶牛的电信(最小割)

    题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相 ...

  6. "XX cannot be resolved to a type "eclipse报错及解决

    好久都没有写博了,还记得自己准备考研,结果你会发现——你永远不知道,你将会走上哪个路. 长远的目标是好的,但有些时候身不由己也迫不得已!做好自己的当下就是好的. 不论搞什么,总会遇到各种各样的问题,以 ...

  7. 【BZOJ1758】【WC2010】重建计划(点分治,单调队列)

    [BZOJ1758][WC2010]重建计划(点分治,单调队列) 题面 BZOJ 洛谷 Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表 ...

  8. 【BZOJ1416/1498】【NOI2006】神奇的口袋(数论,概率)

    [BZOJ1416/1498][NOI2006]神奇的口袋(数论,概率) 题面 BZOJ1416 BZOJ1498 洛谷 题面都是图片形式是什么鬼.. 题解 考虑以下性质 1.\(x[1],x[2]. ...

  9. (转)Ubuntu 17.04_64上搭建巡风扫描系统(资产信息漏洞扫描内网神器)

    巡风简介 巡风是一款适用于企业内网的漏洞快速应急.巡航扫描系统,通过搜索功能可清晰的了解内部网络资产分布情况,并且可指定漏洞插件对搜索结果进行快速漏洞检测并输出结果报表.其主体分为两部分:网络资产识别 ...

  10. Linux内核分析第三周学习博客——跟踪分析Linux内核的启动过程

    Linux内核分析第三周学习博客--跟踪分析Linux内核的启动过程 实验过程截图: 过程分析: 在Linux内核的启动过程中,一共经历了start_kernel,rest_init,kernel_t ...