在程序开发过程中,难免出现这样那样的错误,有些使我们的逻辑导致的错误,也就是我们常说的Bug, 这些都是很容易修复的。有些是我们无法预测的,比如当我们写入文件的时候,文件被删除了,或者磁盘空间满了,在比如网络传输数据,网络突然断了。这类的错误我们称之为异常。
和其他很多语言一样,Python也有自己的异常处理机制。
try...except...finally...
Python的异常完整的结果是这样子的
try:
# 主代码块
pass
except KeyError,e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,执行该块
pass
finally:
# 无论异常与否,最终执行该块
pass
我们先来看一个例子,了解一下基本流程
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print(e)
finally:
pass
print('END')
我们都知道0不能做除数,在程序中,一旦遇到除数为零的情况,任何语言都会出现异常。
执行结果
try...
except: division by zero
finally...
END
从执行结果来看,当程序运行到10 / 0
的时候,遇到了异常,所以异常被捕获到,但是后面的语句print('result:', r)
没有执行,但是并影响程序的继续运行,try
块外面的部分是不受到影响的得以继续运行。所以print('END')
正常输出了。另外except
表示匹配后面的错误类型,错误ZeroDivisionError
就是表示除数为零的错误。所以被except ZeroDivisionError as e:
匹配到,所以print(e)
。as e
表示将错误信息赋值给一个变量e
。这个变量名可以随意。
从语法上和if
语句很像,可以匹配多个条件,也就是可以有多个except
,匹配多个异常。最后的finally
表示前面的错误都没有匹配到要执行的块。
另外Python的异常捕获可以跨层捕获,比如我们定义了一个函数,函数里面出现了异常,我们可以在调用这个函数的代码块中捕获
def foo():
return 10 / 0
try:
foo()
except ZeroDivisionError as e:
print(e)
执行结果
division by zero
常见异常
Python内置了一些常见异常
`AttributeError`:试图访问一个对象没有的成员
`IOError`:输入/输出异常;基本上是无法打开文件
`ImportError`:无法引入模块或包;基本上是路径问题或名称错误
`IndentationError`:语法错误(的子类);代码没有正确对齐
`IndexError`:下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
`KeyError`:试图访问字典里不存在的键
`KeyboardInterrupt`:`Ctrl+C`被按下,也就是试图强制退出程序
`NameError`:使用一个还未被赋予对象的变量
`SyntaxError`:Python代码非法,代码不能编译,也就是语法错误
`TypeError`:传入对象类型与要求的不符合
`UnboundLocalError`:试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
`ValueError`:传入一个调用者不期望的值,即使值的类型是正确的
`Exception`:代表所有异常(当然不是所有异常都能被捕获至少`KeyboardInterrupt`就不能被它捕获)
几个创建异常例子
dic = ["wupeiqi", 'alex']
try:
dic[10]
except IndexError, e:
print e
dic = {'k1':'v1'}
try:
dic['k20']
except KeyError, e:
print e
s1 = 'hello'
try:
int(s1)
except ValueError, e:
print e
主动抛出异常
有的时候我们出于某种目的,比如强制让他传一个什么样类型的数据。需要主动抛出异常,Python中我们通过raise
关键字
def foo(s):
if not isinstance(s, int):
raise ValueError('这里需要传入一个整数类型')
else:
print(int(s))
try:
foo(12)
foo('hello')
except ValueError as e:
print(e)
执行结果
12
这里需要传入一个整数类型
当我们传入的是一个整数的时候,没有问题,当我传入一个字符串的额时候由于if not isinstance(s, int):
判断出来参数不是整数类型,所以主动通过raise ValueError('这里需要传入一个整数类型')
抛出了异常。
自定义异常
除了Python自带的异常以外,我们也可以自定义一个异常。定义一个异常就是定义一个类,继承自Exception
class customException(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message
try:
raise customException('这是自定义的异常')
except customException as e:
print(e)
执行结果
这是自定义的异常