1.什么是异常
Python用异常对象(exception object)来表示异常情况。遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(traceback)终止信息。例:
>>> 1/0
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
2.按自己的方式出错
raise语句
为了引发一个异常,可以使用一个类(应该是Exception的子类)或者实例参数调用raise语句。使用类时,程序会自动创建一个类的实例。例:
>>> raise Exception
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
Exception
>>> raise Exception("can't be zero")
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
Exception: can't be zero
第一个例子raise Exception引发了一个没有任何有关错误信息的普通异常。后一个例子中,则添加了错误信息“can’t be zero”。
一些内建异常
Exception:所有异常的基类
AttributeError:特性应用或赋值失败时引发
IOError:试图打开不存在文件(包括其他情况)时引发
IndexError:在使用序列中不存在的索引时引发
KeyError:在使用映射中不存在的键时引发
NameError:在找不到名字(变量)时引发
SyntaxError:在代码为错误形式时引发
TypeError:在内建操作或者函数应用于错误类型的对象时引发
ValueError:在内建操作或者函数应用于正确类型的对象,但是该对象使用不合适的值时引发
ZeroDivisionError:在除法或者模除操作的第二个参数为0时
自定义异常类
跟创建其他类一样,只要确保从Exception类继承(不管是间接的还是直接的)即可。例:
>>> class SomeCustomException(Exception):
... pass
...
3.捕捉异常
使用try/except语句来处理异常。
使用try/except捕获异常。例:
>>> try:
... x = input("input a number : ")
... y = input("input another number : ")
... print x/y
... except ZeroDivisionErro:
... print "the second number can't be zero !"
...
input a number : 10
input another number : 0
Traceback (most recent call last):
File "<stdin>", line 5, in <module>
NameError: name 'ZeroDivisionErro' is not defined
即使已经捕获了异常,但是又想重新引发它,就那么可以调用不带参数的raise。例:
>>> class MuffledCalculator:
... muffled = False
... def cal(self, expr):
... try:
... return eval(expr)
... except ZeroDivisionError:
... if self.muffled:
... print 'Division by zero is illegal !'
... else:
... raise
...
>>> calculator = MuffledCalculator()
>>> calculator.cal('10/2')
5
>>> calculator.cal('10/0')
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "<interactive input>", line 5, in cal
File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> calculator.muffled = True
>>> calculator.cal('10/0')
Division by zero is illegal !
上例中通过muffled的值打开和关闭了屏蔽机制。
用一个块捕捉多个异常
如果需要用一个块捕捉多个类型异常,那么可以将它们作为元组列出。例:
>>> try:
... x = input("input a number : ")
... y = input("input another number : ")
...
... print x/y
... except (ZeroDivisionErro, TypeError, NameError):
... print 'your numbers were bogus ....'
捕捉对象
如果希望在except子句中访问异常对象本身,可以使用两个参数(注意:就算要捕捉到多个异常,也只需向except子句提供一个参数——一个元组)。例:
>>> try:
... x = input("input a number : ")
... y = input("input another number : ")
...
... print x/y
... except (ZeroDivisionErro, TypeError, NameError), e:
... print e
注:在python3.0中,except子句会被写作except(ZeroDivisionErro, TypeError, NameError) as e
真正的全捕捉
如果想用一段代码捕捉所以异常,那么可以在except子句中忽略所有的异常类。例:
>>> try:
... x = input("input a number : ")
... y = input("input another number : ")
...
... print x/y
... except :
... print 'something is wrong !'
注:像上例中的这种捕捉方式比较危险,因为他会隐藏所有程序员未想到的并且未做好准备处理的错误。它同样会捕捉用户终止执行的Ctrl+C企图,以及用sys.exit函数终止程序的企图等。这时用except Exception, e会更好些,或者对异常对象e进行一些检查。
万事大吉
有些情况中,没有坏事发生时执行一段代码是很有用的,可以相对条件和循环语句那样,给try/except语句加个else子句,如果主try块中没有异常发生,else子句就会被执行。例:
>>> try:
... print 'A simple task'
... except :
... print 'What? Something went wrong !'
... else:
... print 'Ah ......It went as planned !'
...
A simple task
Ah ......It went as planned !
可以使用else子句实现循环。例:
>>> try:
... x = input("input a number : ")
... y = input("input another number : ")
... print x/y
... except :
... print 'invalid input. Please try again !'
... else:
... break
注:这里的循环只有在没有异常的情况下才会退出(有else子句中的break语句退出)。只要有错误发生,程序会不断要求重新输入。
最后………
finally子句,它可以用来在可能的异常后进行清理。它和try子句联合使用。例:
>>> x = None
>>> try:
... x =1/0
... finally:
... print 'Cleaning up.....'
... del x
...
Cleaning up.....
Traceback (most recent call last):
File "<interactive input>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> x
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
NameError: name 'x' is not defined
注:上例中,finally子句肯定会被执行,不管try子句是否发生异常。
还可以在同一条语句中组合使用try、except、finally和else(或者其中三个)。例:
>>> try:
... x =1/0
... except NameError, e:
... print 'unknown variable !'
... else:
... print 'That were well !'
... finally:
... print 'Cleaning up.....'
...
Cleaning up.....
Traceback (most recent call last):
File "<interactive input>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero
4.异常和函数
异常和函数可以一起工作。如果异常在函数内引发而不被处理,它就会传播至函数调用的地方。如果那里也没有处理异常,它就会继续传播,一直到达主程序,如果那里也没有处理异常 ,程序会带着栈淙淙终止。例:
>>> def faulty():
... raise Exception('Somethins is wrong !')
...
>>> def ignore_faulty():
... faulty()
...
>>> def handle_exception():
... try:
... faulty()
... except:
... print 'Exception handled !'
...
>>> ignore_faulty()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "<interactive input>", line 2, in ignore_faulty
File "<interactive input>", line 2, in faulty
Exception: Somethins is wrong !
>>> handle_exception()
Exception handled !
5.本章的新函数
warnings.filterwarnings(action, …..) : 用于过滤警告