封面图片来源:沙沙野
异常处理什么是异常处理?Python 解释器检测到错误就会触发异常,或者程序员自己触发异常
程序中编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关)
如果捕捉成功则进入另外一个处理分支,执行为其定制的逻辑,使程序不会崩溃,这就是异常处理
2. 为什么要进行异常处理?Python 解析器去执行程序,检测到了一个错误时,触发异常
异常触发后且没被处理的情况下,程序就在当前异常处终止,后面的代码不会运行。
所以必须提供一种异常处理机制来增强程序的健壮性与容错性
3. 如何进行异常处理?首先须知,异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前就修正
try:
l1 = [1, 2, 3]
l1[100] # 代码运行到这里就结束了
print(111)
dic = {"key1": "v1"}
dic["key2"] # 这里不会报错
except IndexError:
print("索引值超过了范围,程序报错")
# 运行结果:
索引值超过了范围,程序报错
4. except 的错误与实际报错对不上的情况
try:
dic = {"key1": "v1"}
dic["key2"]
except IndexError as i:
print("索引错误")
# 运行结果:
Traceback (most recent call last):
File "test01.py", line 4, in
dic["key2"]
KeyError: 'key2'
# 之所以不显示 IndexError 的内容
# 是因为这不是 IndexError, 而是 KeyError
5. 多个 except 的情况
try:
l1 = [1, 2, 3]
l1[100]
print(111)
dic = {"key1": "v1"}
dic["key2"]
num = int(input("请输入数字:"))
except KeyError as kIndex:
print(111)
except IndexError as i:
print(222)
except ValueError as v:
print(333)
# 运行结果:
222
# 根据 Python 逐行解释、从上往下的执行方式
# 先捕捉到某个异常之后,就执行相对 except 的异常处理
6. 万能异常
try:
l1 = [1, 2, 3]
l1[100]
print(111)
dic = {"key1": "v1"}
dic["key2"]
num = int(input("请输入数字:"))
except Exception as e:
print(e)
# 运行结果:
list index out of range
# 同理,先捕捉哪个异常就提示对应的错误信息
# 此时,程序已经结束执行,后面及时还有异常也不管了
7. 上面的方法不是说哪一种就绝对好,应该视情况来写异常处理。如果对报错信息不关心,只是想直接跳过报错而不分流执行代码,使用万能异常。
s = "hello"
try:
int(s)
except Exception as e:
print(e)
print("即使捕捉到了异常,只要使用的是万能异常处理的,程序就还能够继续执行")
# 运行结果:
invalid literal for int() with base 10: 'hello'
即使捕捉到了异常,只要使用的是万能异常处理的,程序就还能够继续执行
8. 虽然使用 Exception 是可以捕捉所有异常,但也意味着在处理所有异常时都使用同一个逻辑去处理。如果想要捕捉具体的错误信息,根据不同的错误执行不同的分支,则使用多分支比较好
s = 'hello'
try:
int(s)
except IndexError as i:
print(i)
except KeyError as k:
print(k)
except ValueError as v:
print(v)
# 运行结果:
invalid literal for int() with base 10: 'hello'
9. 使用多分支的时候,最后加上一个 Exception 使逻辑更加完整
s = 'hello'
try:
int(s)
except IndexError as i:
print(i)
except KeyError as k:
print(k)
except ValueError as v:
print(v)
except Exception as e:
print(e)
10. 异常处理的其他方式
s = 'hello'
try:
int(s)
except IndexError as i:
print(i)
except KeyError as k:
print(k)
except ValueError as v:
print(v)
else:
print("如果 try 代码块的内容没有异常就执行我")
finally:
print("无论上面的逻辑是否有异常,我都会被执行")
# 运行结果:
invalid literal for int() with base 10: 'hello'
无论上面的逻辑是否有异常,我都会被执行
11. finally 的作用非常强大,程序有没有异常它都会执行,可以用在多个地方。比如关闭文件句柄,数据库链接等
with open("test", encoding="utf-8") as f:
try:
pass
finally:
f.close()
12. 自定义异常
try:
raise TypeError('类型错误')
except Exception as e:
print(e)
# 自定义异常
class EvaException(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self):
return self.msg
try:
raise EvaException('类型错误')
except EvaException as e:
print(e)
13. 异常处理 try...except... 总结try...except... 这种异常处理机制就是取代 if 条件语句,目的是让程序在不牺牲可读性的前提下增强健壮性和容错性
异常处理中为每一个异常定制了异常类型,对于同一个异常,一个 except 就可以捕捉到,可以同时处理多段代码的异常,无需写多个 if 判断,减少代码,增强了可读性
把错误处理和真正的工作分开来,代码更易组织,更清晰,复杂的工作任务更容易实现
另外,还有一点:不至于由于一些小的疏忽而使程序意外崩溃
虽然上面列举了各种优点,但是 try...except... 应该尽量少用,因为它本身就是附加给程序的一种异常处理的逻辑,与主要的工作是没多大关系的
PS: 为了方便大家相互交流、解决学习过程中遇到的问题,我新建了一个 QQ 群,感兴趣的小伙伴加进来一起学习吧!~ (群号码:697678250,加群请备注:笔记)