错误:没法通过其他代码进行处理的问题 语法错误、逻辑错误
异常:多指程序在执行过程中,出现未知错误,语法和逻辑都是正确的,可以通过其他代码进行处理修复
常见的系统异常
# 1、除零异常
# 1 / 0
# 2、名称异常
# print(name)
# 3、类型异常
# "1" + 2
# 4、索引异常
l = [1, 2]
# l[3]
# 键异常
dic = {"name":"yl", "age":18}
# dic["add"]
# 值异常
# int("abc")
# 属性异常
# name = "yl"
# print(name.xx)
# 迭代器异常
it = iter([1, 2])
print(next(it))
print(next(it))
# print(next(it))
# 自己定义的异常
# 继承自Exception
异常的解决
系统一开始已经内置了一些特定的应用场景,当我们写代码的过程当中,一旦触发了这个场景,系统内部就会自动向外界抛出这个场景,也就是所谓的异常不去处理这个异常,就是程序被终止执行,导致软件的崩溃
- 预防
添加容错代码,容错代码过多,会造成代码混乱,主业务不清晰 - 捕捉异常
# try:
# print(name) # 可能出现异常的代码
# except NameError: # 你要捕捉异常的类别
# print("名称有问题,请仔细检查") # 对异常处理
# else:
# # 没有出现异常的处理
# finally:
# # 不管有没有出现异常都会执行的代码
try:
1 / 0
print(name) # 从上往下检测,先检测先处理
except ZeroDivisionError as ze:
print("除零错误:", ze)
except NameError as ne:
print("名称错误:", ne)
finally:
print("不管有没有出现异常都会执行的代码")
# 合并处理多个异常
try:
1 / 0
print(name) # 从上往下检测,先检测先处理
except (ZeroDivisionError, NameError):
print("异常")
finally:
print("不管有没有出现异常都会执行的代码")
try:
1 / 0
print(name) # 从上往下检测,先检测先处理
except Exception as e:
print("异常", e)
finally:
print("不管有没有出现异常都会执行的代码")
# with语句
# 适用于执行某段代码A之前,进行预处理,执行代码A结束之后,进行清理操作
# 文件读取的正常步骤:打开、读取、关闭
# 要保证,不管读取文件操作有没有异常,都要关闭文件
# try:
# 打开文件
# 读取文件
# finally:
# 关闭文件
# 上述过于繁琐
try:
f = open("resouce/JPG/IMG_9327.JPG", "r") # 应该以二进制文件读取"rb"
f.readlines()
except Exception as e:
print("异常提示", e)
finally:
print("xxx")
f.close()
# 方案二
with open("resouce/JPG/IMG_9327.JPG", "r") as f:
f.readlines()
# 自定义上下文管理器
class Test:
def __enter__(self):
print("enter")
return "xxxx"
def __exit__(self, exc_type, exc_val, exc_tb):
print(self, exc_type, exc_val, exc_tb)
print("exit")
with Test() as x: # 先enter -> body -> exit
# x是enter方法执行的返回值
print("body", x) # x:"xxxx"
- contextlib模块
@contextlib.contextmanager 通过一个装饰器让生成器快速变成一个上下文管理器
# 生成器
# 让生成器通过一个装饰器快速变成一个上下文管理器
import contextlib
@contextlib.contextmanager # 上下文管理器有进有出,有返回值
contextlib.closing快速让拥有close()方法的对象变成上下文管理器
def test():
print(1) # yield前面当作enter
yield "xxx"
print(2) # yield后面当作exit
with test() as x:
print(3, x) # 当作中间部分
# 把主要业务逻辑部分和异常处理部分进行分离
@contextlib.contextmanager
def ze():
try:
yield
except ZeroDivisionError as e:
print("error:", e)
x = 1
y = 0
with ze(): # 上下文管理器,先yield上面try->x/y->yield下面exception
x / y
class test:
def t(self):
print("tttt")
def close(self):
print("资源释放")
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
with test() as t_obj: # t是enter方法返回值,恰恰是对象本身
t_obj.t()
class test:
def t(self):
print("tttt")
def close(self):
print("资源释放")
# contextlib.closing快速让拥有close()方法的对象变成上下文管理器
with contextlib.closing(test()) as t_obj: # t是enter方法返回值,恰恰是对象本身
t_obj.t()
- 手动抛出异常
# 手动抛出异常
# 通过raise语句直接抛出异常
def setAge(age):
if age <= 0 or age >= 20:
# print("error")
raise ValueError("值错误")
else:
print("设置年龄", age)
- 自定义异常
# 自定义异常
class LessZero(Exception): # 继承Exception
def __init__(self, msg, error_code):
self.msg = msg
self.ec = error_code
def __str__(self):
return self.msg + str(self.ec)
pass
def setAge(age):
if age <= 0 or age >= 20:
# print("error")
raise LessZero("值错误", 404)
else:
print("设置年龄", age)
try:
setAge(-90)
except LessZero as l:
print("x", l)