第八章:异常
什么是异常
python用异常对象(ecxeption object)来表示异常情况。遇到错误之后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(traceback,一种错误信息)终止执行。
事实上,每个异常都是一些类的实例,这些实例可以被引发,并且可以用很多方法进行捕捉,使得程序可以捉住错误并且对其进行处理,而不是让整个程序失效。如何引发异常,以及创建自己的异常类型。
raise语句
为了引发异常,可以使用一个类(应该是Exception的子类)或者实例参数调用raise语句。使用类时,程序会自动创建类的一个实例。
>>>raise Exception
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-67-fca2ab0ca76b> in <module>()
----> 1 raise Exception
Exception:
>>>raise Exception('hyperdrive overload')
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-68-b31edcf659a9> in <module>()
----> 1 raise Exception('hyperdrive overload')
Exception: hyperdrive overload
第二个例子引发了错误,并且添加了错误信息。
- 内建的异常类有很多。python库参考手册的built-in exceptions一节中有关于它们的描述。用交互式解释器可以分析它们,这些内建异常都可以在exceptions模块(和内建的命名空间)中找到。
类名 | 描述 |
---|---|
Exception | 所有异常的基类 |
AttributeError | 特性引用或赋值失败时引发 |
IOError | 试图打开不存在文件(包括其他情况)时引发 |
IndexError | 在使用序列中不存在的索引时引发 |
KeyError | 在使用映射中不存在的键时引发 |
NameError | 在找不到名字(变量时)引用 |
SyntaxError | 在代码为错误形式时引发 |
TypeError | 在内建操作或者函数引用于错误类型的对象时引发 |
ValueError | 在内建操作或者函数应用于正确类型的对象,但是该对象使用不合适的值时引发 |
ZeroDivisinError | 在除法或者模除操作的第二个参数为0时引发 |
- 自定义异常类
只是要确保从Exception类继承(不管是间接的或者直接的,也就是说继承其他的内建异常类也是可以的)。
class SomeCunstomException(Exception):pass
- 捕捉异常
try:
x = input("enter a number:")
y = input("enter another number:")
print x/y
except ZeroDivisionError:
print "the second number can't be zero"
多个except语句:
try:
x = input("enter a number:")
y = input("enter another number:")
print x/y
except ZeroDivisionError:
print "the second number can't be zero"
except TypeError:
print "That wasn't a number. was it?"
用一个块捕捉两个异常:
try:
x = input("enter a number:")
y = input("enter another number:")
print x/y
except(ZeroDivisionError,TypeError,NameError):
print "Your number were bogus……"
捕捉异常对象本身:
try:
x = input("enter a number:")
y = input("enter another number:")
print x/y
except (ZeroDivisionError,TypeError,NameError),e:
print e
在python3中,except子句会被写作except (ZeroDivisionError,TypeError,NameError) as e:
真正的全捕捉:
x = input("enter a number:")
y = input("enter another number:")
print x/y
except Exception,e: #也可以直接except:但是,这样的捕捉所有异常时危险的,因为它会隐藏所有程序员未想到并且未做好准备处理的错误。
print "something wrong happened"
enter a number:1
enter another number:
something wrong happened
在没有遇到异常时,可以执行else语句,如下:
while True:
try:
x = input("enter a number:")
y = input("enter another number:")
print x/y
except:
print 'invalid input. Please try again.'
else:
break;
最后……
最后,是finally子句。它可以用来在可能的异常后进行清理。它和try子句联合使用。
finally子句肯定会被执行,不管是否发生异常。
try:
x = 1/0
finally:
print '...'
- 异常和函数:
异常和函数能很自然的在一起工作。如果异常在函数内引发而不被处理,它就会传播至(浮到)函数调用的地方。如果在那里也没有处理异常,它就会继续传播,一直到达主程序(全局作用域)。如果那里没有异常处理程序,程序就会带着栈跟踪终止。