Python - 异常处理
异常与错误的概念
错误:苹果内部坏了只能扔
没法通过其他的代码进行处理的问题
语法错误:比如 定义函数写成了 dfe xxx()
这种错误,直接通过IDE或者解释器给出的提示进行修改
逻辑错误:语法层面没有问题,但是自己设计的逻辑出现问题
例如: if age<18: print(‘已经成年’)
这种错误,IDE或者解释器无法帮我们检查出,只有通过代码测试进行排查
异常:苹果只是脏了,洗洗还能吃
程序在执行过程中,出现的未知错误;语法和逻辑都是正常的;可以通过其他代码进行处理修复
例如:想获取一个数字,但用户输入了字符
在x/y 中,输入的y为0
类型
除零异常
1/0
ZeroDivisionError
名称异常
print(name)
NameError
索引异常
a = [1,2]
a[3]
IndexError
键异常
dic = {‘name’:‘sz’}
dic[‘abd’]
KeyError
值异常
int(‘abc’)
ValueError
属性异常
name = ‘sz’
print(name.xx)
AttributeError
迭代器异常
it = ite([1,2])
print(next(it))
print(next(it))
print(next(it))
Stoplteration
系统异常类继承树
BaseExption 分为SystmExit KeyboardInter等等
异常:
系统一开始已经内置了一些应用场景,在我们写代码的过程中,一旦触发了这个场景,系统内部就会自动的向外界抛出这个问题,也就是我们所谓的异常
预防:添加容错代码,加if 判断一下
解决:有些场景无法语法,只能捕捉后处理掉,例子如下
try:
print(name)
except NameError:
print('名称有问题,请仔细检查')
#不会报错了,有输出
语法
try:
可能会出现异常的代码
except 你要捕捉的异常1处理:
对这个异常的处理
except 你要捕捉的异常2处理:
对这个异常的处理
else:
没出现异常时做的处理
finally:
不管有没有出现异常,都会执行的代码
#else,finally这些词的顺序不可以变
当存在多次异常时,从上到下,捕捉到第一次异常后,就会往下匹配下去,不会多次检测
取别名
try:
1/0
except ZeroDivisionError as ze:
print('xxx',ze)
#输出:xxx division by zero
多个异常同时捕捉,用个元组
try:
1/0
#print(name)
except (ZeroDivisionError,NameError) as ze:
print('xxx',ze)
#输出:xxx division by zero
try:
#1/0
print(name)
except (ZeroDivisionError,NameError) as ze:
print('xxx',ze)
#输出:xxx name 'name' is not defined
如果异常名称不确定,又想捕捉,可以直接写Exception
try:
1/0
#print(name)
except Exception as ze:
print('xxx',ze)
#输出:xxx division by zero
with语句
适用于某一段代码之前预处理,执行某段代码之后清理操作
无论这段代码有无异常,都能保证最后的清理操作得到执行
例子:读取文件
1,打开文件 2,读取文件 3,关闭文件
如果2出错,3不会执行,导致文件无法关闭
try:
打开文件
读取文件
finally:
关闭文件
with open(file) as F:
读取文件
#open 已经实习了打开与关闭
try:
f = open('xx.jpg','r')
f.readlines()
finally:
print('xxx')
f.close()
with open('xx.jpg','r') as f:
f.readlines()
上下管理器
上面与下面有一段固定代码
class Test:
def __enter__(self):
print('enter')
def __exit__(self, exc_type, exc_val, exc_tb):
print(self, exc_type, exc_val, exc_tb)
print('exit')
with Test():
print('body')
输出:
enter
body
<__main__.Test object at 0x0000023E3C5CAFD0> None None None
exit
class Test:
def __enter__(self):
print('enter')
return 'xxx'
def __exit__(self, exc_type, exc_val, exc_tb):
print(self, exc_type, exc_val, exc_tb)
print('exit')
with Test() as x:
print('body',x)
#x输出上下管理器的返回值
#return self 时,返回 body <__main__.Test object at 0x0000023E3C5CAFD0>
contexlib模块
生成器变成了上下管理器
import contextlib
@contextlib.contextmanager
def test():
print(1)
yield 'xxx'
print(2)
with test() as x:
print(3,x)
输出:
1
3 xxx
2