2
2
3
3
#错误和异常(1)
4
4
5
- 虽然在前面的学习中,已经遇到了错误和异常问题,但是一直没有很认真的研究它。现在来近距离观察错误和异常 。
5
+ 对于程序在执行过程中因为错误或者别的原因而中止的现象,已经看过多次了,那些都可以归为“错误和异常”现象。本章就要对这种现象进行近距离观察 。
6
6
7
7
##错误
8
8
9
- python中的错误之一是语法错误(syntax errors),比如:
9
+ 不管是小白还是高手,在编写程序的时候,错误往往是难以避免的。可能是因为语法用错了,也可能是拼写做了,当然还可能其它莫名其妙的错误,比如冒号写成了全角的了,等等。总之,编程中有相当一部分工作就是要不停地修改错误。
10
+
11
+ Python中的错误之一是语法错误(syntax errors),比如:
10
12
11
13
>>> for i in range(10)
12
14
File "<stdin>", line 1
13
15
for i in range(10)
14
16
^
15
17
SyntaxError: invalid syntax
16
18
17
- 上面那句话因为缺少冒号` : ` ,导致解释器无法解释,于是报错。这个报错行为是由python的语法分析器完成的 ,并且检测到了错误所在文件和行号(` File "<stdin>", line 1 ` ),还以向上箭头` ^ ` 标识错误位置(后面缺少` : ` ),最后显示错误类型。
19
+ 上面那句话因为缺少冒号` : ` ,导致解释器无法解释,于是报错。这个报错行为是由Python的语法分析器完成的 ,并且检测到了错误所在文件和行号(` File "<stdin>", line 1 ` ),还以向上箭头` ^ ` 标识错误位置(后面缺少` : ` ),最后显示错误类型。
18
20
19
- 错误之二是在没有语法错误之后,会出现逻辑错误。逻辑错误可能会由于不完整或者不合法的输入导致 ,也可能是无法生成、计算等,或者是其它逻辑问题。
21
+ 另一种常见错误是逻辑错误。逻辑错误可能是由于不完整或者不合法的输入导致 ,也可能是无法生成、计算等,或者是其它逻辑问题。
20
22
21
- 当python检测到一个错误时 ,解释器就无法继续执行下去,于是抛出异常 。
23
+ 当Python检测到一个错误时 ,解释器就无法继续执行下去,于是抛出提示信息,即为异常 。
22
24
23
25
##异常
24
26
@@ -27,12 +29,16 @@ python中的错误之一是语法错误(syntax errors),比如:
27
29
>>> 1/0
28
30
Traceback (most recent call last):
29
31
File "<stdin>", line 1, in <module>
30
- ZeroDivisionError: integer division or modulo by zero
32
+ ZeroDivisionError: integer division or modulo by zero #Python 3: ZeroDivisionError: division by zero
31
33
32
- 当python抛出异常的时候 ,首先有“跟踪记录(Traceback)”,还可以给它取一个更优雅的名字“回溯”。后面显示异常的详细信息。异常所在位置(文件、行、在某个模块)。
34
+ 当Python抛出异常的时候 ,首先有“跟踪记录(Traceback)”,还可以给它取一个更优雅的名字“回溯”。后面显示异常的详细信息。异常所在位置(文件、行、在某个模块)。
33
35
34
36
最后一行是错误类型以及导致异常的原因。
35
37
38
+ 在刚才的例子中,明确告诉我们一场的类型是` ZeroDivisionError ` ,并且对此异常类型做了解释(虽然Python 2和Python 3的解释不完全一致,但意思是一样的)。
39
+
40
+ > 为什么0不能作除数(分母)?虽然小学生都知道不能作,但是不一定知道为什么不能作。读者对此有兴趣思考思考吗?
41
+
36
42
下表中列出常见的异常
37
43
38
44
| 异常 | 描述|
@@ -54,7 +60,7 @@ python中的错误之一是语法错误(syntax errors),比如:
54
60
File "<stdin>", line 1, in <module>
55
61
NameError: name 'bar' is not defined
56
62
57
- python中变量需要初始化,即要赋值。虽然不需要像某些语言那样声明,但是要赋值先。 因为变量相当于一个标签,要把它贴到对象上才有意义。
63
+ Python中变量虽然不需在使用变量之前先声明类型,但也需要对变量进行赋值,然后才能使用。不被赋值的变量,不能再Python中存在, 因为变量相当于一个标签,要把它贴到对象上才有意义。
58
64
59
65
###ZeroDivisionError
60
66
@@ -63,7 +69,7 @@ python中变量需要初始化,即要赋值。虽然不需要像某些语言
63
69
File "<stdin>", line 1, in <module>
64
70
ZeroDivisionError: integer division or modulo by zero
65
71
66
- 貌似这样简单的错误时不会出现的 ,但在实际情境中,可能没有这么容易识别,所以,依然要小心为妙。
72
+ 你或许已经有足够的信心,貌似这样简单的错误在你的程序中是不会出现的 ,但在实际情境中,可能没有这么容易识别,所以,依然要小心为妙。
67
73
68
74
###SyntaxError
69
75
@@ -73,9 +79,9 @@ python中变量需要初始化,即要赋值。虽然不需要像某些语言
73
79
^
74
80
SyntaxError: invalid syntax
75
81
76
- 这种错误发生在python代码编译的时候 ,当编译到这一句时,解释器不能讲代码转化为python字节码 ,就报错。只有改正才能继续。所以,它是在程序运行之前就会出现的(如果有错) 。现在有不少编辑器都有语法校验功能,在你写代码的时候就能显示出语法的正误,这多少会对编程者有帮助。
82
+ 这种错误发生在Python代码编译的时候 ,当编译到这一句时,解释器不能讲代码转化为Python字节码 ,就报错。它只在程序运行之前出现 。现在有不少编辑器都有语法校验功能,在你写代码的时候就能显示出语法的正误,这多少会对编程者有帮助。
77
83
78
- ###IndexError
84
+ ###IndexError和KeyError
79
85
80
86
>>> a = [1,2,3]
81
87
>>> a[4]
@@ -98,11 +104,11 @@ python中变量需要初始化,即要赋值。虽然不需要像某些语言
98
104
File "<stdin>", line 1, in <module>
99
105
IOError: [Errno 2] No such file or directory: 'foo'
100
106
101
- 如果你确认有文件,就一定要把路径写正确,因为你并没有告诉python对你的computer进行全身搜索, 所以,python会按照你指定位置去找 ,找不到就异常。
107
+ 如果你确认有文件,就一定要把路径写正确,因为你并没有告诉Python要对你的Computer进行全身搜查。 所以,Python会按照你指定位置去找 ,找不到就异常。
102
108
103
109
###AttributeError
104
110
105
- >>> class A(object): pass
111
+ >>> class A(object): pass #Python 3: class A: pass
106
112
...
107
113
>>> a = A()
108
114
>>> a.foo
@@ -112,18 +118,22 @@ python中变量需要初始化,即要赋值。虽然不需要像某些语言
112
118
113
119
属性不存在。这种错误前面多次见到。
114
120
115
- 其实,python内建的异常也不仅仅上面几个 ,上面只是列出常见的异常中的几个。比如还有:
121
+ Python内建的异常也不仅仅上面几个 ,上面只是列出常见的异常中的几个。比如还有:
116
122
117
123
>>> range("aaa")
118
124
Traceback (most recent call last):
119
125
File "<stdin>", line 1, in <module>
120
126
TypeError: range() integer end argument expected, got str.
121
-
127
+ #Python 3:
128
+ #TypeError: 'str' object cannot be interpreted as an integer
129
+
122
130
总之,如果读者在调试程序的时候遇到了异常,不要慌张,这是好事情,是python在帮助你修改错误。只要认真阅读异常信息,再用` dir() ` ,` help() ` 或者官方网站文档、google等来协助,一定能解决问题。
123
131
124
132
##处理异常
125
133
126
- 在一段程序中,为了能够让程序健壮,必须要处理异常。举例:
134
+ 如果在程序运行过程中,出现了“抛出异常”的现象,程序就会中止运行。这样的程序是不“健壮”的,“健壮”的程序应该是不为各种“异常”所击倒,所以,要在程序里面对各种异常进行处理。
135
+
136
+ Python 2:
127
137
128
138
#!/usr/bin/env python
129
139
# coding=utf-8
@@ -142,6 +152,25 @@ python中变量需要初始化,即要赋值。虽然不需要像某些语言
142
152
print "*************************"
143
153
else:
144
154
break
155
+ Python 3:
156
+
157
+ #!/usr/bin/env python
158
+ # coding=utf-8
159
+
160
+ while 1:
161
+ print("this is a division program.")
162
+ c = input("input 'c' continue, otherwise logout:")
163
+ if c == 'c':
164
+ a = input("first number:")
165
+ b = input("second number:")
166
+ try:
167
+ print(float(a)/float(b))
168
+ print("*************************")
169
+ except ZeroDivisionError:
170
+ print("The second number can't be zero!")
171
+ print("*************************")
172
+ else:
173
+ break
145
174
146
175
运行这段程序,显示如下过程:
147
176
@@ -162,15 +191,15 @@ python中变量需要初始化,即要赋值。虽然不需要像某些语言
162
191
input 'c' continue, otherwise logout:d
163
192
$
164
193
165
- 从运行情况看,当在第二个数,即除数为0时,程序并没有因为这个错误而停止,而是给用户一个友好的提示,让用户有机会改正错误。这完全得益于程序中“处理异常”的设置,如果没有“处理异常”,异常出现,就会导致程序终止 。
194
+ 从运行情况看,当在第二个数,即除数为0时,程序并没有因为这个错误而停止,而是给用户一个友好的提示,让用户有机会改正错误。这完全得益于程序中“处理异常”的设置,如果没有“处理异常”,当异常出现时就会导致程序中止 。
166
195
167
- 处理异常的方式之一,使用 ` try...except... ` 。
196
+ ### ` try...except... ` 。
168
197
169
- 对于上述程序,只看try和except部分 ,如果没有异常发生,except子句在try语句执行之后被忽略;如果try子句中有异常可 ,该部分的其它语句被忽略,直接跳到except部分 ,执行其后面指定的异常类型及其子句。
198
+ 对于上述程序,只看 ` try ` 和 ` except ` 部分 ,如果没有异常发生,` except ` 子句在 ` try ` 语句执行之后被忽略;如果 ` try ` 子句中有异常可 ,该部分的其它语句被忽略,直接跳到 ` except ` 部分 ,执行其后面指定的异常类型及其子句。
170
199
171
- except后面也可以没有任何异常类型 ,即无异常参数。如果这样,不论try部分发生什么异常,都会执行except 。
200
+ ` except ` 后面也可以没有任何异常类型 ,即无异常参数。如果这样,不论 ` try ` 部分发生什么异常,都会执行 ` except ` 。
172
201
173
- 在except子句中 ,可以根据异常或者别的需要,进行更多的操作。比如:
202
+ 在 ` except ` 子句中 ,可以根据异常或者别的需要,进行更多的操作。比如:
174
203
175
204
#!/usr/bin/env python
176
205
# coding=utf-8
@@ -182,7 +211,7 @@ except后面也可以没有任何异常类型,即无异常参数。如果这
182
211
return eval(express)
183
212
except ZeroDivisionError:
184
213
if self.is_raise:
185
- print "zero can not be division."
214
+ print "zero can not be division." #Python 3: "zero can not be division."
186
215
else:
187
216
raise
188
217
@@ -203,13 +232,13 @@ except后面也可以没有任何异常类型,即无异常参数。如果这
203
232
>>> eval("3+5")
204
233
8
205
234
206
- 另外,在except子句中 ,有一个` raise ` ,作为单独一个语句。它的含义是将异常信息抛出。并且,except子句用了一个判断语句 ,根据不同的情况确定走不同分支。
235
+ 另外,在 ` except ` 子句中 ,有一个` raise ` ,作为单独一个语句。它的含义是将异常信息抛出。并且,` except ` 子句用了一个判断语句 ,根据不同的情况确定走不同分支。
207
236
208
237
if __ name__ == "__ main__ ":
209
238
c = Calculator()
210
239
print c.calc("8/0")
211
240
212
- 这时候` is_raise = False ` ,则会:
241
+ 故意出现0做分母的情况。 这时候` is_raise = False ` ,则会:
213
242
214
243
$ python 21602.py
215
244
Traceback (most recent call last):
@@ -218,7 +247,7 @@ except后面也可以没有任何异常类型,即无异常参数。如果这
218
247
File "21602.py", line 8, in calc
219
248
return eval(express)
220
249
File "<string>", line 1, in <module>
221
- ZeroDivisionError: integer division or modulo by zero
250
+ ZeroDivisionError: integer division or modulo by zero #Python 3的信息略有差异
222
251
223
252
如果将` is_raise ` 的值改为True,就是这样了:
224
253
0 commit comments