异常处理
任何语言,异常都包括2种:
- 编译期异常: 自己的错误,如参数传递错误,类型不匹配,指针越界,变量名,方法名写错,除以0的操作,读取不存在的文件
- 运行期异常:断网
python是如何处理异常的?
python处理异常的方法有2种:
- 捕获
- 抛出
1. try..except...捕获异常
try:
代码块1
except:
代码块2
执行流程:从try下面的代码块1开始执行,如果发生异常,则会直接跳入代码块2;如果未发生异常,则只会执行代码块1
fruit = ["apple","pear"]
try:
f = fruit[2]
print(f)
except:
print("列表索引越界啦")
以上代码不回报错,会输出
列表索引越界啦
再来个例子:
fruit = ["apple","pear"]
try:
f = fruit[1]
print(f)
except:
print("列表索引越界啦")
则永远不会执行代码块2
捕获指定异常
try:
代码块1
except 异常X as e:
代码块2
举例:
fruit = ["apple","pear"]
try:
f = fruit[2]
print(f)
except IndexError as e:
print("列表索引越界啦:",e)
列表索引越界啦: list index out of range
捕获指定的多个异常
try:
代码块1
except (异常X,异常Y,异常Z) as e:
代码块2
等价于
try:
代码块1
except 异常X as e:
代码块2
except 异常Y as e:
代码块3
except 异常Z as e:
代码块4
第一种是把异常放在一个except下处理,第二种,是把异常放在不同的except下处理。无论用哪种方式,当程序发生异常时,python会根据异常类型去匹配对应的except语句,然后执行其中的代码块。
若异常没有匹配到,则会继续抛出。那么这2种方式有什么区别呢?
- 第一种方式适用于多种异常可以用相同的代码块去处理
- 第二种方式适用于不同的异常需用不同的代码去处理
try-except-finally
语句
try:
代码块1
except Exception as e:
代码块2
finally:
代码块3
它的执行流程是:
1. 先执行代码块1
2. 如果代码块1出现异常,则跳转到代码块2;如果代码块1未出现异常,则代码块1执行完之后,不回执行代码块2
3. 最后执行代码块3
finally到底有什么用?
打个比方,举个例子,我们有时会在 try 下使用一些资源(比如文件、网络连接),而无论过程中是否有异常产生,我们在最后都应该释放(归还)掉这些资源,这时就可以将释放资源的代码放在 finally 语句下。
2.raise语句主动抛出异常
之前的示例中,异常是在程序遇到错误无法继续执行时,由解释器所抛出,我们也可以选择自己主动抛出异常。
主动抛出异常的方法是使用 raise 语句:
raise ValueError()
也可以同时指明错误原因:
raise ValueError("输入值不符合要求")
我们用示例来学习为什么要主动抛出异常,以及如何主动抛出异常。
之前我们在学习函数的时候写过这样一个函数:
def stage_of_life(age):
if age <= 6:
return '童年'
elif 7 <= age <=17:
return '少年'
elif 18 <= age <= 40:
return '青年'
elif 41 <= age <= 65:
return '中年'
else:
return '老年'
显然这个函数没有应对可能出错的情况。比如函数的 age 参数不能任意取值,要符合人类的年龄范围才行,如果取值超出范围就需要向函数调用方报告错误,这时就可以采取主动抛出异常的方式。
我们在函数内检验输入值的有效性,若输入有误则向外抛出异常,新增第 2 和第 3 行代码:
def stage_of_life(age):
if age < 0 or age > 150:
raise ValueError("年龄的取值不符合实际,需要在 0 到 150 之间")
if age <= 6:
return '童年'
elif 7 <= age <=17:
return '少年'
elif 18 <= age <= 40:
return '青年'
elif 41 <= age <= 65:
return '中年'
else:
return '老年'
stage_of_life(180)
这里检查 age 的范围是否在 0~150 之间,若不是则使用 raise 抛出 ValueError 异常,表示取值错误。
Traceback (most recent call last):
File "a.py", line 16, in <module>
stage_of_life(180)
File "a.py", line 3, in stage_of_life
raise ValueError("年龄的取值不符合实际,需要在 0 到 150 之间")
ValueError: 年龄的取值不符合实际,需要在 0 到 150 之间