十五、异常处理
十五、异常处理
一、什么是异常处理:
异常是错误发生前的一种信号
如果没有人来处理这个信号,程序就会中断执行并抛出错误信息
异常的分类:
1.语法检测异常:这种异常是最低级异常,决不能犯
避免方法:1.如果是编译器,会自动提示错误
2.如果是文本编辑器,在你执行代码前,解释器会检测语法
2.运行时异常(逻辑异常):这种异常只有在代码被执行时才能发现
特点:1.在没有运行代码前,是无法发现的
2.如果运行时异常已经发生并且没有正确处理,就会抛出错误信息
我们要处理的重点就是:逻辑异常
异常的组成:
1.追踪信息:具体发生异常的位置,以及函数的调用顺序
2.异常的类型:错误的类型
3.异常的信息:具体详细的错误信息
我们之所以学习异常处理:为的是让我们的程序更加稳定,不容易崩溃,更加的健壮性
二、常见异常
1 NameError 找不到这个名字 要么变量 要么函数 2 ValueError 在调用一个函数时给的的值不正确 3 TypeError 类型错误 例如字符串与数字加减乘除 调用一个不能被调用的类型 4 ZeroDivisionError 除数不能为0 5 KeyError 没有这个key 6 IndexError 索引不存在 7 StopIteration 没有更多的值可以迭代 8 FileNotFoundError 文件不存在 9 io.UnsupportedOperation 文件的操作不支持 10 AttributeError 没有这个属性 11 KeyboardInterrupt 程序被强行终止 ctrl+c
三、异常处理
要处理异常,要学一个新的语法:
try:
代码块
except 异常类型:
注意:一旦try中有代码抛出异常,后面的代码就不会执行
1 #基本语法: 2 # print("staring.....") 3 # try: 4 # name 5 # except NameError: 6 # print("名字找不到!") 7 # print("end.......") 8 9 # 多种异常类型处理 10 # print("staring.....") 11 # try: 12 # name 13 # [][-1] 14 # pass 15 # except NameError: 16 # print("名字找不到!") 17 # except IndexError: 18 # print("索引超出范围") 19 # print("end.......") 20 21 22 # 当代码可能出现多种异常时的写法 23 # print("staring.....") 24 # try: 25 # # name 26 # # [][-1] 27 # 1/0 28 # pass 29 # except NameError: 30 # print("名字找不到!") 31 # except IndexError: 32 # print("索引超出范围") 33 # except ZeroDivisionError: 34 # print("除数不能为0") 35 # print("end.......") 36 37 # 当代码可能出现多种异常时的写法2 38 # print("staring.....") 39 # try: 40 # {}["aaa"] 41 # # name 42 # # [][-1] 43 # 1/0 44 # except (NameError,IndexError,ZeroDivisionError): 45 # print("可能名字找不到! 可能所以超出范围 可能除数为0") 46 # print("end.......") 47 48 # 上面两种写法 都可以处理多种异常 但是 异常类型太多了 不可能全写完 49 # 万能异常类型 Exception 或BaseException 基于OOP的继承和多态 50 print("staring.....") 51 try: 52 # {}["aaa"] 53 # name 54 # [][-1] 55 1/0 56 except Exception: 57 print("可能名字找不到! 可能所以超出范围 可能除数为0") 58 print("end.......")
四、不太常用的语法
语法1:
try:
except:
else: try中没有发生异常就会执行
语法2:
try:
except:
finally: try中无论是否发生异常都会执行,一般用来回收系统资源
1 # print("start...") 2 # try: 3 # # 1/0 4 # [][1] 5 # pass 6 # except ZeroDivisionError: 7 # print("除数异常") 8 # except NameError: 9 # print("名字异常") 10 # else: 11 # print("else会在 try中没有异常时执行") 12 # print("end...") 13 14 15 # finally 16 # print("start...") 17 # try: 18 # # 1/0 19 # # [][1] 20 # pass 21 # except ZeroDivisionError: 22 # print("除数异常") 23 # except IndexError: 24 # print("索引异常") 25 # else: 26 # print("else会在 try中没有异常时执行") 27 # finally: 28 # print("finally 无论异常是否发生 都会执行!") 29 # print("end...") 30 31 32 # 使用finally来回收资源 33 try: 34 f = open(r"D:\上海python全栈4期\day31\异常处理\1今日内容","rt",encoding="utf-8") 35 f.read() 36 # f.write("123") 37 except Exception: 38 print("发生异常了") 39 finally: 40 print("关闭文件!") 41 f.close() 42 43 44 print(f.closed)
五、主动抛出异常
当程序中有一些限制,然而用户没有遵守时,我们可以主动抛出异常
语法:
raise 异常类型(异常的详细信息)
类型必须是baseexception的子类
1 raise NameError("这就是名字不存在异常!") 2 3 age = input("请输入整型的年龄:") 4 if not age.isdigit(): 5 raise TypeError("你输入的不是整型!") 6 age = int(age) 7 print("十年后你%s岁" % (age + 10))
六、断言
断言:可以理解为断定,就是很清楚,很明确
什么时候需要用断言:当下面的代码必须依赖上面代码的正确数据时
语法:
assert 结果为bool的表达式
如果值为True 则继续往下执行代码
如果值为False 则抛出一个AssertionError 表示断言失败
没有assert也可以使用if 来完成,assert仅仅是简化了代码
1 # 第一部分代码 负责产生一个列表 2 li = [] 3 # li.append(1) 4 # li.append(2) 5 # 这里一定要确保数据是有效的 6 # if len(li) < 1: 7 # raise ValueError("列表中没有数据!") 8 assert len(li) > 0 9 # 需要使用列表中的数据来完成任务 如果没有数据无法完成 10 print(li[0]) 11 print(li[0]) 12 print(li[0]) 13 print(li[0])
七、自定义异常类型
当系统提供的这些异常类型和你要描述的错误不匹配时,就需要自定义异常类型
写法:
class 自定义异常的类型名称继承BaseException:
总结:之所以自定义异常类型,就是为了更具体的描述你的错误,让使用者一眼就看出
关键点:在except中,使用as来获取异常对象
1 class UnletterUpper(BaseException): 2 def __init__(self,msg1,msg2): 3 self.msg1=msg1 4 self.msg2=msg2 5 6 def func(): 7 name=input('>>>>:') 8 if name.isupper(): 9 raise UnletterUpper('名字不能大写','下次请输入小写') 10 else: 11 print('输入正确') 12 13 try: 14 func() 15 except UnletterUpper as letter: 16 print(letter)