学习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
有异常发生,并且捕获异常,最后在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
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
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
然后,我们在看看把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
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
但是,当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
分析: 这里因为没有发生异常, 所以会执行到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
看到这里,我们貌似找到了一些规律
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 语句返回最终修改的返回值, 和第一条一致。
python try except else finally 执行顺序详细分析,布布扣,bubuko.com
python try except else finally 执行顺序详细分析
原文地址:http://blog.csdn.net/watkinsong/article/details/27350553