一个程序在运行过程中,难免出现异常。比如访问的文件路径不存在;数值计算过程中出现除0的情况,或者达到了Infinity而溢出;申请内存时,操作系统返回了失败......捕获程序运行异常,并有针对性的对异常进行适当的处理,有利于程序运行的稳定和可靠。
异常与bug有相似之处,比如访问一个不存在的文件,对于程序来说,它虽然不能控制此文件是否存在,但是却可以通过捕获这个异常来让程序进行妥善的处理。对程序增加各种异常情况的处理,可以说也是在解决bug。
用try...except...结构来捕获异常
使用try...except...结构,可以使Python程序在运行过程中,如果出现异常,不至于程序崩溃退出。
>>> a = 1/0
Traceback (most recent call last):
File "", line 1, in
ZeroDivisionError: division by zero
>>> try:
... a = 1/0
... except:
... pass
...
>>>
除0,会产生ZeroDivisionError异常,如果代码不放在try里面,程序直接够崩溃退出了。这是try...except...结构的最基本的用途。而我们除了不让程序崩溃退出,还希望能够捕获到具体的异常信息。请继续看下面的代码:
>>> try:
... a = 1/0
... except BaseException as e:
... print(repr(e))
...
ZeroDivisionError('division by zero')
except这一行的写法有些固定,BaseException是Python中所有的异常类型的基类,所有异常类型,包括自定义的类型,都要从这个类派生。在except分支中个,打印异常信息,注意这里使用的是repr()函数(repr()函数和str()函数的异同)。
如何区别对待不同的异常
在except中使用BaseException,可以捕获所有的异常。不过,很多时候,我们希望能够针对不同的异常,实现不同的处理。请看下面的测试代码:
>>> def test_exception(num):
... try:
... a = 1/num
... if num == 1:
... import os
... os.remove('not existed file')
... except ZeroDivisionError as e:
... print('1---',repr(e))
... except FileNotFoundError as e:
... print('2---',repr(e))
... except:
... print('unknown exception')
...
>>> test_exception(0)
1--- ZeroDivisionError('division by zero')
>>> test_exception(1)
2--- FileNotFoundError(2, 'No such file or directory')
>>> test_exception(3)
在except语句后面跟不同的异常类型,就可以对异常进行区别处理。try...except...语句结构,一个try后面可以跟很多个except,每个except都可以对应某个不同的异常处理分支。其实,一个except还可以同时包含多个异常,即相当于我们对某几个不同的异常,采用同样的处理:
>>> import os
>>> def test_exception2(num):
... try:
... a = 1/num
... if num == 1: os.remove('NotExistedFile')
... except (ZeroDivisionError, FileNotFoundError) as e:
... print('3---', repr(e))
...
>>> test_exception2(0)
3--- ZeroDivisionError('division by zero')
>>> test_exception2(1)
3--- FileNotFoundError(2, 'No such file or directory')
except后面跟着的多个异常类型,要把它们写成tuple的形式。
except后面的as
本文上面的测试代码,except语句后面基本都有as e,as的作用是将异常对象赋值给变量e,这样在except结构中,就可以直接通过repr(e)来获取异常的信息。
也可以不写as,如果你的代码不需要访问异常对象的话。比如下面这样:
>>> try:
... a = float('abcde')
... except:
... print('excepton occur')
...
excepton occur
>>> try:
... a = float('abcde')
... except ValueError:
... print('value error')
...
value error
这些写法都OK,只是异常处理代码就拿不到异常对象了,一般不建议这样写。
代码中有了异常捕获和处理,Python程序就会显得更加健壮。
-- EOF --