异常处理的能力是一门语言好坏的重要特征。python也提供了强大的异常处理功能,如下面介绍。
1. try...except :
try:
#raise NameError
pass
except NameError:
# code to be executed when NameError occurred
pass
except ValueError:
# code to be executed when NameError occurred
pass
上述代码的执行规则如下:
首先,执行try语句中的语句。
如果在执行的过程中出现异常,则立即停止try语句的执行,执行异常处理或者停止执行(异常没有处理)
发生异常后,将异常类型按顺序与except语句中的异常匹配,如果匹配成功,执行对应的异常处理。如果匹配不成功。将异常传递给更高一级的try语句,如果异常一直未找到处理程序则停止执行,抛出异常信息。
执行流程图如下:
有几点需要注意:
- 出现异常时一旦类型匹配成功,就执行该类型对应的异常处理。此后不再继续匹配,也就是说最多(不匹配时不执行)只有一个异常处理代码块被执行。
- 一个except语句可以处理多种类型(组成元组)的异常,格式如下: except (RuntimError, TypeError, NameError):
- except中可以引用异常的实例, except NameError as inst : 或者 except NameError, inst .如果出现NameError异常,err就是这个异常的实例。可以操作这个实例的方法或者属性获得更多的异常信息。
例如:
try:
raise Exception('spam', 'eggs')
except Exception as inst :
print(type(inst)) #<class 'Exception'>
print(inst.args) #(argument tuple)
print(inst) #
这段代码中,抛出异常时我们传递了两个参数 spam和eggs,这两个参数被组成一个元组,存储在异常实例的args属性中,因此print inst.args将输出(‘spam’, 'eggs').由于这个异常实例定义了__str__方法,所以可以直接将它输出,输出结果与print inst.args一样。如果一个传递了参数的异常没有被处理,那么在抛出的异常信息最后一部分会是所传递的参数。假设上面抛出的异常没有处理(即去掉except语句),则输出的异常信息最后一部分是:Exception: ('spam', 'eggs')
2. try ... except ... else:
else语句是可选的,它在没有出现异常的时候被执行。也就是说,try语句没有异常时,执行else语句。try语句出现异常时,按照1中的规则执行,忽略else语句。
3. try...finally
try:
#You do your operations here;
pass
#Due to any exception, this may be skipped.
finally:
pass
#This would always be executed.
在这种情形中,finally语句总会被执行,无论try是否出现异常。
下面是一个很好的例子:
try:
fh = open("testfile", "w")
try:
fh.write("This is my test file for exception handling!!")
finally:
fh.close()
except IOError:
print("Error: can\'t find file or read data")
else :
print("Everything goes well")
上述代码中,在执行内部try语句时,写完文件之后,finally一定会被执行,也就是文件一定会关闭。这段代码中有两处可能出现异常,open和write。如果在open出现异常,内部try不被执行,直接进行异常处理输出“Error: can\'t find file or read data”。如果open不出现异常,继续执行内部try,无论内部try是否出现异常close总会被执行。内部try出现异常,由于内部try没有except语句,所以异常被传递给外部try语句,匹配IOError成功,执行异常处理,输出“Error: can\'t find file or read data”。不出现异常的时候,执行else语句。
另一个例子:
def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
执行divide(2, '2')时,结果如下:
executing finally clause
Traceback (most recent call last):
File "D:\eclipse\workspace\python\exception\try_exception.py", line 11, in <module>
divide(2,'2')
File "D:\eclipse\workspace\python\exception\try_exception.py", line 3, in divide
result = x / y
TypeError: unsupported operand type(s) for /: 'int' and 'str'
4. raise 抛出异常
除了程序运行时出现异常外,我们也可以人为地抛出任意类型的异常。e.g:
raise NameError("TEST")
raise后面只能跟着一个异常。这个异常可是是异常类,也可是是异常实例。
如果你只想知道是否出现异常,不想去处理异常,有一种方法可以重新抛出异常:
try:
raise NameError("Hello")
except NameError:
print "a NameEerror occurs"
raise
这段代码执行结果如下:
a NameEerror occurs
Traceback (most recent call last):
File "<pyshell#1>", line 2, in <module>
raise NameError("Hello")
NameError: Hello
Traceback (most recent call last):
File "<pyshell#1>", line 2, in <module>
raise NameError("Hello")
NameError: Hello
5. 自定义异常
python允许程序员通过继承内置的异常类型来定制自己的异常类型。
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
try:
raise MyError(4)
except MyError as inst:
print("opps, MyError occurred, value:", inst.value)
这段代码执行结果为:opps, MyError occurred, value: 4
自定义异常类型的时候,尽量保持简单,提供有效的异常信息即可。
以上几点只是简单介绍,详细内容请参考官方文档。