python异常处理

摘要

在写python程序过程中,难免会遇到各种各样的异常和错误。而我们可以用下面的语句来捕捉到错误并进行处理,或者在我们需要的地方主动抛出一个异常。本文就对python中的错误、异常处理简单做一下说明和整理。

运用场景

  • 让程序兼容性更强
  • 发生错误时可以进行处理,让程序继续运行
  • 主动抛出异常

异常列表

python2

异常 描述
Exception 所有异常的基类
NameError 尝试访问一个没有申明的变量
SyntaxError 语法错误
TypeError 类型错误
KeyError 请求一个不存在的字典关键字
KeyboardInterrupt Ctrl+C
IOError 输入输出错误(比如你要读的文件不存在)
ZeroDivisionError 除数为0
IndexError 索引超出序列范围
AttributeError 尝试访问未知的对象属性
ValueError 传给函数的参数类型不正确,比如给int()函数传入字符串形
AssertionError assert语句失败
ImportError 导入模块或包错误
IdentationError 语法错误,没有对齐
1
2
3
4
5
6
7
8
9
10
11
12
13
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的

python3

待续

异常处理

异常基础

在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!

1
2
3
4
try:
pass
except Exception,ex:
pass

异常种类

python中的异常种类非常多,每个异常专门用于处理某一项异常!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
###
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
###
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
###
s1 = 'hello'
try:
int(s1)
except IndexError,e:
print e
except KeyError,e:
print e
except ValueError,e:
print e
###
s1 = 'hello'
try:
int(s1)
except KeyError,e:
print '键错误'
except IndexError,e:
print '索引错误'
except Exception, e:
print '错误'
###

异常其他结构

1
2
3
4
5
6
7
8
9
10
11
12
try:
# 主代码块
pass
except KeyError,e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,执行该块
pass
finally:
# 无论异常与否,最终执行该块
pass

主动触发异常

1
2
3
4
try:
raise Exception('错误了。。。')
except Exception,e:
print e

自定义异常

1
2
3
4
5
6
7
8
9
10
11
12
class WupeiqiException(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message
try:
raise WupeiqiException('我的异常')
except WupeiqiException,e:
print e

try…except…

  • try…except…
  • try…except…else…

当我们尝试打开一个不存在的文件时,python就会给我们抛出一个错误,python2是IOError,python3是FileNotFoundError。

1
2
3
4
5
6
7
8
9
10
11
# python2
>>> open("test.txt")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'test.txt'
# python3
>>> open("test.txt")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'

以 python2 的处理为例,如果我们已经知道会发生的错误类型,这时候我们就可以通过一个异常处理来捕捉到这个错误,并进行处理。

1
2
3
4
5
6
>>> try:
... open("test.txt")
... except IOError:
... print "get error"
...
get error

运行上述代码,我们发现没有看到任何错误,并且打印了”get error”,说明我们已经用except捕捉到了IOError这个错误,然后输出了一个字符串(或者也可以直接pass,什么都不做)。

而当我们不是打开一个文件,而是打印一个不存在的变量呢。

1
2
3
4
5
6
7
8
>>> try:
... print var
... except IOError:
... print "get error"
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
NameError: name 'var' is not defined

这时候又有错误抛出,并且这时候不是IOError了 而是NameError,而我们的except捕捉的不是这个错误。所以错误还是会抛出,这时候我们只要把except后面的异常改成NameError就行了。

1
2
3
4
5
>>> try:
... print var
... except Exception as e::
... pass
...

我们也可以用上面这种方式来捕捉到所有的异常。

try…finally…

  • try…finally…
  • try…except…finally…

这样的语句,中间不管捕捉到了什么,最后finally下面的代码都会运行,我们可以使用这种语句做一些类似清理,管理连接的操作。这里就不做演示了

异常其他结构

1
2
3
4
5
6
7
8
9
10
11
try:
# 主代码块
pass
except KeyError,e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,执行该块
pass
finally:
# 无论异常与否,最终执行该块

异常的抛出机制:

  • 如果在运行时发生异常,解释器会查找相应的处理语句(称为handler).
  • 要是在当前函数里没有找到的话,它会将异常传递给上层的调用函数,看看那里能不能处理。
  • 如果在最外层(全局“main”)还是没有找到的话,解释器就会退出,同时打印出traceback以便让用户找到错误产生的原因。
  • 注意:虽然大多数错误会导致异常,但一个异常不一定代表错误,有时候它们只是一个警告,有时候它们可能是一个终止信号,比如退出循环等。

raise 异常抛出

1
2
3
4
5
6
7
8
>>> name = raw_input("name:")
name:cass
>>> if name == "cass":
... raise NameError("wrong name")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
NameError: wrong name

使用raise我们可以主动抛出一个异常。

1
2
3
4
5
6
7
8
9
10
11
12
class Continue(Exception):
pass
for i in range(100):
try:
name = raw_input("name:")
if name == "cass":
raise Continue()
except Continue:
continue
finally:
print name

自定义异常

1
2
3
4
5
6
7
8
9
10
11
12
class WupeiqiException(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message
try:
raise WupeiqiException('我的异常')
except WupeiqiException,e:
print e

assert断言

python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。

  • assert expression [, arguments]
  • assert 表达式 [, 参数]
1
2
3
4
assert 1==1
assert 2+2==2*2
assert len(['my boy',12])<10
assert range(4)==[0,1,2,3]