1. 编程时通常会遇到的两类错误
一类是语法错误,就是不按 Python 规定的语法来写代码,这也是初学者最容易犯的错误,比如:
>>> print(“I love FishC.”)
SyntaxError: invalid character '“' (U+201C)
另一类错误并非由于语法错误导致的:
>>> 1 / 0
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
1 / 0
ZeroDivisionError: division by zero
2. 异常机制
Python 通过提供异常机制来识别及响应错误。
Python 的异常机制可以分离出程序中的异常处理代码和正常业务代码,使得程序代码更为优雅,并提高了程序的健壮性。
Python 内置异常大合集 -> 传送门(Python 的所有内置异常,全部都在这里了,大家遇到看不懂的异常信息,直接打开这个网页,然后 Ctrl+F,输入异常的名称就可以)
3. 处理异常
利用 try-except 语句来捕获并处理异常语法如下:
try:
检测范围
except [expression [as identifier]]:
异常处理代码
举个例子:
>>> try:
... 1 / 0
... except:
... print("出错了~")
...
出错了~
我们可以在 except 后面指定一个异常:
>>> try:
... 1 / 0
... except ZeroDivisionError:
... print("除数不能为0。")
...
除数不能为0。
后面还有一个可选的 as,这样的话可以将异常的原因给提取出来:
>>> try:
... 1 / 0
... except ZeroDivisionError as e:
... print(e)
...
division by zero
在这个代码中,但凡检测到 try 语句中包含这三个异常中的任意一个,都会执行 pass 语句,直接忽略跳过。
最后也可以单独处理不同的异常,使用多个 except 语句就可以了:
>>> try:
... 1 / 0
... 520 + "FishC"
... except ZeroDivisionError:
... print("除数不能为0。")
... except ValueError:
... print("值不正确。")
... except TypeError:
... print("类型不正确。")
...
除数不能为0。
4. 处理异常
try-except-else
try-except 还可以跟 else 进行搭配,它的含义就是当 try 语句没有检测到任何异常的情况下,就执行 else 语句的内容:
>>> try:
... 1 / 0
... except:
... print("逮到了~")
... else:
... print("没逮到~")
...
逮到了~
如果在 try 语句中检测到异常,那么就执行 except 语句的异常处理内容:
>>> try:
... 1 / 1
... except:
... print("逮到了~")
... else:
... print("没逮到~")
...
1.0
没逮到~
try-except-finally
跟 try-except 语句搭配的还有一个 finally,就是说无论异常发生与否,都必须要执行的语句:
>>> try:
... 1 / 0
... except:
... print("逮到了~")
... else:
... print("没逮到~")
... finally:
... print("逮没逮到都会咯吱一声~")
...
逮到了~
逮没逮到都会咯吱一声~
>>> try:
... 1 / 1
... except:
... print("逮到了~")
... else:
... print("没逮到~")
... finally:
... print("逮没逮到都会咯吱一声~")
...
1.0
没逮到~
逮没逮到都会咯吱一声~
finally 通常是用于执行那些收尾工作,比如关闭文件的操作:
>>> try:
... f = open("FishC.txt", "w")
... f.write("I love FishC.")
... except:
... print("出错了~")
... finally:
... f.close()
这样的话,无论 try 语句中是否存在异常,文件都能够正常被关闭。
现在我们的异常处理语法变成了这样:
try:
检测范围
except [expression [as identifier]]:
异常处理代码
[except [expression [as identifier]]:
异常处理代码]*
[else:
没有触发异常时执行的代码]
[finally:
收尾工作执行的代码]
或者:
try:
检测范围
finally:
收尾工作执行的代码
5异常的嵌套
异常也是可以被嵌套的:
>>> try:
... try:
... 520 + "FishC"
... except:
... print("内部异常!")
... 1 / 0
... except:
... print("外部异常!")
... finally:
... print("收尾工作~")
...
内部异常!
外部异常!
收尾工作~
6raise 语句
使用 raise 语句,我们可以手动的引发异常:
>>> raise ValueError("值不正确。")
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
raise ValueError("值不正确。")
ValueError: 值不正确。
注意,你不能够 raise 一个并不存在的异常哈:
>>> raise FishCError("小甲鱼说你不行你就不行~")
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
raise FishCError("小甲鱼说你不行你就不行~")
NameError: name 'FishCError' is not defined
7 assert 语句
assert 语句跟 raise 类似,都是主动引发异常,不过 assert 语句只能引发一个叫 AssertionError 的异常。
这个语句的存在意义,通常是用于代码调试:
>>> s = "FishC"
>>> assert s == "FishC" # 得到期待的结果,通过
>>> assert s != "FishC" # 没有得到期待的结果,引发异常
Traceback (most recent call last):
File "<pyshell#72>", line 1, in <module>
assert s != "FishC"
AssertionError
8 利用异常来实现 goto
有学过 C 语言的同学应该听到过一个叫做 goto 的语句,虽然用的不多,但有时候,有这么一个可以指哪跳哪的功能,可以说是非常方便,比如说要在多个嵌套循环语句里面一把跳出来,就非常方便了……可惜 Python 没有!
>>> try:
... while True:
... while True:
... for i in range(10):
... if i > 3:
... raise
... print(i)
... print("被跳过~")
... print("被跳过~")
... print("被跳过~")
... except:
... print("到这儿来~")
...
0
1
2
3
到这儿来~