在这篇文章中,我们将通过5个实例,逐步介绍一下Python中 try except else finally语句的使用,以及如何使用raise主动抛出异常。
对于一个程序来说,即使在语法上是完全正确的,但是在执行过程中仍然可能会出现一些不可控的语义上的异常错误。比如我们通过让用户输入两个数字,然后将两个数字相除,如果用户输入的除数是0,在进行除法时,就会导致异常。再比如我们正在读写一个较大的文件,但是在读取的过程中磁盘损坏了,也会产生异常。为了处理这些在运行时出现的状况,Python提供了一套捕获和处理异常的机制。下面我们通过一个小程序来看一下异常处理的基本架构。
![3d567f55b0f4cb1c843efd7511cf76c8.png](https://i-blog.csdnimg.cn/blog_migrate/49cb04dbabcc95c7754148000635b3ce.jpeg)
首先,在try和except之间的语句将被执行。如果没有发生异常,则程序执行完try和except之间的语句后将退出。如果执行过程中任意语句出现异常,将跳至except语句处理相对应的异常。在上面的程序中,我们特意设计了一个除数为0的除法,程序在执行过程中,将抛出除以0的异常,然后被except捕获到,因此执行了print "捕获到异常,除数为0"的语句。程序的执行效果如下:
![69961bbe311e6ac62036a4aa1a26006d.png](https://i-blog.csdnimg.cn/blog_migrate/88a07c1bcdfae8d5b90df119feab5521.jpeg)
Python中有很多内置异常,当发生异常后,将根据异常的类型匹配对应的处理程序进行处理。比如ArithmeticError(算术错误),IOError(输入输出错误)等等。不同的错误类型有不同的处理步骤。下面我们看一下将如何处理多个异常。
![1909af05d95bfaaf47a142218bd968f3.png](https://i-blog.csdnimg.cn/blog_migrate/1f3af2d0c45ab09bc54c125de31731af.jpeg)
在这个程序中,我们设计了两个捕获异常的代码,并且我们在执行到int("abc")时,由于abc是不能转换成整数的,所以强行让程序抛出了异常。通过执行的结果,我们可以看到,程序最终捕获并处理了ValueError。在这里,由于我们的程序有两个问题点,一个是除法可能抛出除0的异常,一个是类型转换为整数时,可能产生数值错误,因此我们定义了两个except,哪个异常产生,就单独处理哪个异常。程序的执行效果如下:
![eeec7e4a3682161624f32d50807c023b.png](https://i-blog.csdnimg.cn/blog_migrate/1f3eb6524a37c63ff03e768f208071f0.jpeg)
Python还提供了else子句,当程序执行完try和except之间的语句,没有任何错误时,将执行else子句。
![1e879041521827d7e11cbf59e3d70975.png](https://i-blog.csdnimg.cn/blog_migrate/d616a90f2760d713bdb6df28d0d2f855.jpeg)
以上程序,没有任何异常发生,因此程序在执行完try和except之间的语句后,会执行else中的语句。Python这样设计的目的,是为了防止else子句中的程序意外的抛出异常,而被前面的except程序捕获并处理。通过使用else子句,try和excep之间的程序出现异常,可以由当前代码段进行有针对性的处理,而如果else子句的代码出现异常,将由调用它们的上级代码进行捕获并处理,互相都不干扰,处理异常也更有针对性。
程序的执行效果如下:
![b87519639dc1feb1d4bf7c05286a330d.png](https://i-blog.csdnimg.cn/blog_migrate/c1d6b9517cbd6c27477bbe5ea0312ccd.jpeg)
通常在实际工作中,我们在进行一段操作时,会有初始化的过程,结束一段操作时,会有一个清理的过程。因此,为了避免由于产生异常,导致清理工作未完成,那么Python为我们设计了finally子句。当程序离开try子句之后,将总是会执行finally子句中的代码段。现在我们展示一个完整的捕获和处理异常的程序架构。
![42486ae386a1ea34f5939aa47eccf072.png](https://i-blog.csdnimg.cn/blog_migrate/fb7ca976befa0db77c7c89da155c3512.jpeg)
首先是执行try子句中的代码,进行初始化工作,然后开始进行各项正常操作。如果过程中我们产生异常,将匹配except对应的异常类型,并进行异常处理。如果没有任何异常产生,将执行else子句。全部执行完毕后,不管是否产生了异常,都将执行finally子句执行清理程序,并退出程序。这就是一个完整的异常处理架构。
程序的执行效果如下:
![042a38e8742dd78e7aef375f973738cd.png](https://i-blog.csdnimg.cn/blog_migrate/2ed024240b5a0f4e1f6e08e987ffbb45.jpeg)
在Python中,我们也可以通过raise语句人为的抛出异常,我们稍微改动一下上面的程序,看一下执行效果。
![d18240eaa32cf640d21451862e31612f.png](https://i-blog.csdnimg.cn/blog_migrate/321f022e8c454641f72022aac8beaa3c.jpeg)
程序的执行效果如下:
![3bc1c86615267944f6ef42504e6fe332.png](https://i-blog.csdnimg.cn/blog_migrate/c1e1785d2c1a6d15246eaea6e41fb71d.jpeg)
在这个程序里,我们使用raise抛出了一个除0的异常,因此通过程序的执行效果可以看出,后面的print"程序进行各项工作"这个语句,就没有再执行,而是执行了except的处理程序。由于程序抛出过异常,因此else子句就不再执行,而finally子句是不管是否产生异常的,所以它仍然被执行,所以如果你有一些清理工作就一定要放在这里,这样可以保证清理工作不会受到异常是否发生的干扰。
以上就是关于Python异常处理的基本介绍。大家可以在实际工作中再根据实际情况慢慢体会一下。
我使用的环境:Windows 7 + Python 2.7.17 + PyCharm Community Edition 2016.1.5
如果大家认为我的文章还可以,真心希望能帮我点一个"关注",粉丝的数量真的对我很重要,也算是对我努力结果的一个支持,谢谢大家了。