python try except else finally 执行顺序详细分析

 

python try except else finally 执行顺序详细分析

分类: Python   193人阅读  评论(0)  收藏  举报

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


1. 没有return 语句的情况


[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. print 'this is a test of code path in try...except...else...finally'  
  2. print '************************************************************'  
  3.   
  4. def exceptTest():  
  5.     try:  
  6.         print 'doing some work, and maybe exception will be raised'  
  7.         raise IndexError('index error')  
  8.         #print 'after exception raise'  
  9.         #return 0  
  10.           
  11.     except KeyError, e:  
  12.         print 'in KeyError except'  
  13.         print e  
  14.         #return 1  
  15.     except IndexError, e:  
  16.         print 'in IndexError except'  
  17.         print e  
  18.         #return 2  
  19.     except ZeroDivisionError, e:  
  20.         print 'in ZeroDivisionError'  
  21.         print e  
  22.         #return 3  
  23.     else:  
  24.         print 'no exception'  
  25.         #return 4  
  26.     finally:  
  27.         print 'in finally'  
  28.         #return 5  
  29.   
  30. resultCode = exceptTest()  
  31. print resultCode  

上面的代码是一直要使用的代码,只不过暂时不用的代码被comment了。

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

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. this is a test of code path in try...except...else...finally  
  2. ************************************************************  
  3. doing some work, and maybe exception will be raised  
  4. in IndexError except  
  5. index error  
  6. in finally  
  7. None  

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


2. 添加return 语句的情况


[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. print 'this is a test of code path in try...except...else...finally'  
  2. print '************************************************************'  
  3.   
  4. def exceptTest():  
  5.     try:  
  6.         print 'doing some work, and maybe exception will be raised'  
  7.         raise IndexError('index error')  
  8.         print 'after exception raise'  
  9.         return 0  
  10.           
  11.     except KeyError, e:  
  12.         print 'in KeyError except'  
  13.         print e  
  14.         return 1  
  15.     except IndexError, e:  
  16.         print 'in IndexError except'  
  17.         print e  
  18.         return 2  
  19.     except ZeroDivisionError, e:  
  20.         print 'in ZeroDivisionError'  
  21.         print e  
  22.         return 3  
  23.     else:  
  24.         print 'no exception'  
  25.         return 4  
  26.     finally:  
  27.         print 'in finally'  
  28.         return 5  
  29.   
  30. resultCode = exceptTest()  
  31. print resultCode  

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

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. this is a test of code path in try...except...else...finally  
  2. ************************************************************  
  3. doing some work, and maybe exception will be raised  
  4. in IndexError except  
  5. index error  
  6. in finally  
  7. 5  

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


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

代码如下:

[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. print 'this is a test of code path in try...except...else...finally'  
  2. print '************************************************************'  
  3.   
  4. def exceptTest():  
  5.     try:  
  6.         print 'doing some work, and maybe exception will be raised'  
  7.         raise IndexError('index error')  
  8.         print 'after exception raise'  
  9.         return 0  
  10.           
  11.     except KeyError, e:  
  12.         print 'in KeyError except'  
  13.         print e  
  14.         return 1  
  15.     except IndexError, e:  
  16.         print 'in IndexError except'  
  17.         print e  
  18.         return 2  
  19.     except ZeroDivisionError, e:  
  20.         print 'in ZeroDivisionError'  
  21.         print e  
  22.         return 3  
  23.     else:  
  24.         print 'no exception'  
  25.         return 4  
  26.     finally:  
  27.         print 'in finally'  
  28.         #return 5  
  29.   
  30. resultCode = exceptTest()  
  31. print resultCode  

这个时候的程序输出:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. this is a test of code path in try...except...else...finally  
  2. ************************************************************  
  3. doing some work, and maybe exception will be raised  
  4. in IndexError except  
  5. index error  
  6. in finally  
  7. 2  

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


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

代码如下:

[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. print 'this is a test of code path in try...except...else...finally'  
  2. print '************************************************************'  
  3.   
  4. def exceptTest():  
  5.     try:  
  6.         print 'doing some work, and maybe exception will be raised'  
  7.         #raise IndexError('index error')  
  8.         print 'after exception raise'  
  9.         #return 0  
  10.           
  11.     except KeyError, e:  
  12.         print 'in KeyError except'  
  13.         print e  
  14.         return 1  
  15.     except IndexError, e:  
  16.         print 'in IndexError except'  
  17.         print e  
  18.         return 2  
  19.     except ZeroDivisionError, e:  
  20.         print 'in ZeroDivisionError'  
  21.         print e  
  22.         return 3  
  23.     else:  
  24.         print 'no exception'  
  25.         return 4  
  26.     finally:  
  27.         print 'in finally'  
  28.         return 5  
  29.   
  30. resultCode = exceptTest()  
  31. print resultCode  

这个时候的代码输出:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. this is a test of code path in try...except...else...finally  
  2. ************************************************************  
  3. doing some work, and maybe exception will be raised  
  4. after exception raise  
  5. no exception  
  6. in finally  
  7. 5  

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


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

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

[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. print 'this is a test of code path in try...except...else...finally'  
  2. print '************************************************************'  
  3.   
  4. def exceptTest():  
  5.     try:  
  6.         print 'doing some work, and maybe exception will be raised'  
  7.         #raise IndexError('index error')  
  8.         print 'after exception raise'  
  9.         return 0  
  10.           
  11.     except KeyError, e:  
  12.         print 'in KeyError except'  
  13.         print e  
  14.         return 1  
  15.     except IndexError, e:  
  16.         print 'in IndexError except'  
  17.         print e  
  18.         return 2  
  19.     except ZeroDivisionError, e:  
  20.         print 'in ZeroDivisionError'  
  21.         print e  
  22.         return 3  
  23.     else:  
  24.         print 'no exception'  
  25.         return 4  
  26.     finally:  
  27.         print 'in finally'  
  28.         return 5  
  29.   
  30. resultCode = exceptTest()  
  31. print resultCode  

执行结果:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. this is a test of code path in try...except...else...finally  
  2. ************************************************************  
  3. doing some work, and maybe exception will be raised  
  4. after exception raise  
  5. in finally  
  6. 5  

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

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


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


[python]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. print 'this is a test of code path in try...except...else...finally'  
  2. print '************************************************************'  
  3.   
  4. def exceptTest():  
  5.     try:  
  6.         print 'doing some work, and maybe exception will be raised'  
  7.         raise IndexError('index error')  
  8.         print 'after exception raise'  
  9.         return 0  
  10.           
  11.     except KeyError, e:  
  12.         print 'in KeyError except'  
  13.         print e  
  14.         return 1  
  15.     except IndexError, e:  
  16.         print 'in IndexError except'  
  17.         print e  
  18.         return 2  
  19.     except ZeroDivisionError, e:  
  20.         print 'in ZeroDivisionError'  
  21.         print e  
  22.         return 3  
  23.     else:  
  24.         print 'no exception'  
  25.         return 4  
  26.     finally:  
  27.         print 'in finally'  
  28.         #return 5  
  29.   
  30. resultCode = exceptTest()  
  31. print resultCode  

执行结果:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. this is a test of code path in try...except...else...finally  
  2. ************************************************************  
  3. doing some work, and maybe exception will be raised  
  4. in IndexError except  
  5. index error  
  6. in finally  
  7. 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 语句返回最终修改的返回值, 和第一条一致。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Pythontry-except-else-finally是一种异常处理机制,用于处理可能会导致程序崩溃的代码块。它们的作用如下: - try:尝试执行一段可能会引发异常的代码。 - except:在try发生异常时执行的代码块。 - else:在try没有发生异常时执行的代码块。 - finally:无论try是否发生异常,都会执行的代码块。 下面是一个简单的例子,演示了这些关键字的使用方法: ```python try: # 尝试执行代码块 f = open("file.txt", "r") except FileNotFoundError: # 文件不存在,执行这里的代码块 print("File not found") else: # 如果try块没有发生异常,执行这里的代码块 print(f.read()) f.close() finally: # 无论try是否发生异常,都会执行这里的代码块 print("Execution complete") ``` 在这个例子,程序尝试打开一个文件,如果文件不存在,则会引发FileNotFoundError异常。如果try块成功执行,它将读取文件并关闭文件。无论发生什么,最后都会执行“Execution complete”的语句。 希望这可以帮助你理解try-except-else-finally关键字在Python的使用方式。 ### 回答2: Pythontryexcept、else、finally是一种异常处理机制,用于处理程序在运行过程出现的异常。以下是对这四个关键字的详细解释: 1. try:用于包含可能发生异常的代码块,并且必须与except、else和finally关键字一起使用。 2. except:用于捕获try代码块的异常,如果try代码块没有异常,则不会执行except代码块。 3. else:用于在try代码块没有异常时执行的代码块,通过执行else代码块,我们可以保证在没有异常时执行特定的代码,否则我们需要让异常处理代码块执行。 4. finally:用于包含必须在tryexcept代码块完成后必须执行的代码。即使tryexcept代码块发生了异常,finally代码块也会执行。 以下是Python处理异常的具体流程: 程序首先执行try代码块的语句,如果没有异常,则执行else代码块的语句,最后执行finally代码块的语句。如果try代码块出现异常,程序将跳到与异常匹配的except代码块,执行相应的异常处理语句,最后执行finally代码块的语句。 在Python,我们可以有多个except代码块,每个except都会捕获不同类型的异常。我们也可以使用Exception关键字捕获所有的异常类型。另外,还可以使用raise关键字在代码手动触发异常,并使用assert关键字来检测特定条件是否为真,如果不是,则触发异常。 总之,利用tryexcept、else、finally这四个关键字,Python可以方便而有效地处理程序运行时可能出现的各种异常情况。 ### 回答3: Pythontry except else finally结构是一种异常处理机制,它允许我们在程序运行时捕获并处理错误,从而使程序更加健壮、容错能力更强。try except else finally结构可以分为以下几个部分: 1. try块:try块是我们尝试执行的代码块,其包含我们可能想要捕获异常的代码。 2. except块:except块是我们处理异常的代码块,它指定了我们想要捕获的异常类型。当try出现异常时,程序会跳转到except块,并执行其的代码。 3. else块:else块是在try块未发生异常时执行的代码块。如果try的代码成功执行,那么程序会自动跳到else块,并执行其的代码。 4. finally块:finally块是在try块和except块均执行完毕后执行的代码块。无论是否出现异常,程序都会执行finally的代码。 下面是一个例子: ```python try: x = int(input("请输入一个数字:")) except ValueError: print("输入错误,您需要输入一个数字") else: print("您输入的数字为:", x) finally: print("程序执行完毕") ``` 该程序会提示用户输入一个数字,如果用户输入的不是数字,则会触发ValueError异常,程序会跳转到except块,并输出一条错误消息。如果用户输入的是数字,则会跳转到else块,并输出用户输入的数字。无论何时,程序都会执行finally的代码,并显示“程序执行完毕”。 总之,Pythontry except else finally结构是一种非常有用的异常处理机制,可以帮助我们避免程序运行时出现的错误,提高程序的健壮性和容错能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值