Python学习笔记(十三):异常处理机制

关于Python的异常处理机制

  • Python学习笔记(十三):异常处理机制
  • 一.异常处理机制
    • 常见异常类型
  • 二.异常处理
    • try...except
    • 异常类的继承体系
    • 多异常捕获
    • 访问异常信息
    • else 块
  • 三.资源回收
  • 四.获取异常信息
    • sys.exc_info()
    • traceback模块
  • 五.raise语句
  • 六.异常处理机制的正确使用

一.异常处理机制

异常处理机制,在程序运行出现错误时,让Python解释器执行事先准备好的除错程序,进而尝试恢复程序的执行借助异常处理机制,可以做到在程序崩溃前将内存中的数据写入文件、关闭打开的文件、释放分配的内存等Python异常处理机制,可以让程序中的异常处理代码和正常业务代码分离,,提高程序的健壮性

常见异常类型

语法错误
SyntaxError语法错误属于真正意义上的错误,只有将程序中的所有语法错误全部纠正,程序才能执行
运行时错误程序在语法上是正确的,但在运行时发生了错误,把这种运行时产生错误的情况叫做异常(Exceptions)

常见异常类型

异常类型 含义
AssertionError 当 assert 关键字后的条件为假时,程序运行会停止并出现异常
AttributeError 当访问的对象属性不存在
IndexError 索引超出序列范围
KeyError 字典中查找一个不存在的关键字
NameError 访问一个未声明的变量
TypeError 不同类型数据之间的无效操作
ZeroDivisionError 除法运算中除数为 0

二.异常处理

try…except

try:#业务代码...
except (Error1, Error2, ...) as e:alert 输入不合法goto retry1.在执行try块里的业务代码时出现异常,系统自动生成一个异常对象,会被提交给Python解释器,这个过程被称为引发异常2.当解释器收到异常对象时,寻找处理该异常对象的except块,找到合适的 except块,则把该异常对象交给该except块处理,这个过程被称为捕获异常3.如果解释器找不到捕获异常的except块,则运行时环境终止,解释器退出4.不管程序代码块是否处于try块中,包括except块中的代码;只要执行该代码块时出现了异常,系统总会自动生成一个 Error 对象5.如果程序没有为这段代码定义任何的 except 块,解释器无法找到处理该异常的except块,程序在此退出

异常类的继承体系

每个except块都是专门用于处理该异常类及其子类的异常实例当解释器接收到异常对象后,会依次判断该异常对象是否是 except 块后的异常类或其子类的实例,如果是,将调用该except块;否则,再次将该异常对象和下一个except块里的异常类进行比较Python的所有异常类都从 BaseException 派生而来,有丰富的异常类,这些异常类之间有严格的继承关系

Python的所有异常类的基类是 BaseException,如果要实现自定义异常,应该继承 Exception 类BaseException 的主要子类就是Exception,不管是系统的异常类,还是用户自定义的异常类,都应该从Exception派生
import sys
try:a = int(sys.argv[1])b = int(sys.argv[2])c = a / bprint("输入的两个数相除的结果是:", c )
except IndexError:print("索引错误:输入的参数个数不够")
except ValueError:print("数值错误:只能接收整数参数")
except ArithmeticError:print("算术错误")
except Exception:print("未知异常")导入sys模块,通过 sys 模块的argv列表来获取运行程序时提供的参数sys.argv[0] 通常代表正在运行的程序名,sys.argv[1]代表运行程序所提供的第一个参数,sys.argv[2]代表运行程序所提供的第二个参数……
  • 在运行该程序时输入的参数不够,会发生索引错误,调用 IndexError 对应的 except 块处理该异常

  • 在运行该程序时输入的参数不是数字,而是字母,将发生数值错误,调用 ValueError 对应的 except 块处理该异常

  • 在运行该程序时输入的第二个参数是 0,将发生除 0 异常,调用 ArithmeticError 对应的 except 块处理该异常

  • 在程序运行时出现其他异常,该异常对象总是 Exception 类或其子类的实例,调用 Exception 对应的 except 块处理该异常

进行异常捕获时应该把Exception类对应的except块放在最后,所有父类异常的except块都应该排在子类异常的except块的后面先捕获小异常,再捕获大异常

多异常捕获

在使用一个 except 块捕获多种类型的异常时,将多个异常类用圆括号括起来,中间用逗号隔开,就是构建多个异常类的元组import sys
try:a = int(sys.argv[1])b = int(sys.argv[2])c = a / bprint("输入的两个数相除的结果是:", c )
except (IndexError, ValueError, ArithmeticError):print("程序发生了数组越界、数字格式异常、算术异常之一")
except: #*print("未知异常")*只有except关键字,省略异常类的except语句也是合法的,表示可捕获所有类型的异常,一般会作为异常捕获的最后一个except块

访问异常信息

在 except 块中访问异常对象的相关信息,通过为异常对象声明变量来实现所有的异常对象都包含了如下几个常用属性和方法:args:该属性返回异常的错误编号和描述字符串
errno:该属性返回异常的错误编号
strerror:该属性返回异常的描述宇符串
with_traceback():通过该方法可处理异常的传播轨迹信息
def test():try:fis = open("you.txt");except Exception as e:print(e.args)         # 访问异常的错误编号和详细信息print(e.errno)        # 访问异常的错误编号print(e.strerror)     # 访问异常的详细信息
test()
(2, 'No such file or directory')
2
No such file or directory访问异常对象,在单个异常类或异常类元组(多异常捕获)之后使用 as 加上异常变量

else 块

在Python的异常处理流程中还可添加一个 else 块,当 try 块没有出现异常时,程序会执行 else 块当 try 块没有异常,而 else 块有异常时,体现出 else 块的作用else 必须和 try except 搭配使用
def else_test():s = input('输入除数:')result = 20 / int(s)print('20除以%s的结果是: %g' % (s , result))
def wrong_main():try:print('try块的代码,没有异常')else_test()  # 将else_test放在try块代码的后面except:print('程序出现异常')
def right_main():try:print('try块的代码,没有异常')except:print('程序出现异常')else:else_test()    # 将else_test放在else块中wrong_main()
right_main()try块的代码,没有异常
输入除数:0
程序出现异常
try块的代码,没有异常
输入除数:0
ZeroDivisionError: division by zero定义了一个else_test() 函数,在运行时需要接收用户输入的参数,输入数据的不同可能导致异常定义了right_main() 和 wrong_main() 两个函数,right_main() 将 else_test() 函数放在 else 块内;wrong_main() 将 else_test() 函数放在 try 块的代码的后面
当 try 块和 else 块都没有异常时,将 else_test() 函数放在 try 块的代码的后面和放在 else 块中没有任何区别如果输入的数据让 else_test() 函数出现异常(try 块没有异常)将 else_test() 函数放在 try 块的代码的后面,此时 else_test() 函数运行产生的异常将会被 try 块对应的 except 捕获,这是异常处理机制的执行流程将 else_test() 函数放在 else 块中,当 else_test() 函数出现异常时,程序没有 except 块来处理该异常,该异常会传播给解释器,导致程序中止放在 else 块中的代码所引发的异常不会被 except 块捕获,如果希望某段代码的异常能被后面的 except 块捕获,那么就应该将这段代码放在 try 块的代码之后

三.资源回收

finally只要求和try搭配使用,没有规定该结构中是否包含except和 else(else 必须和 try except 搭配使用)finally语句在异常处理机制中的功能:无论 try 块是否发生异常,都要进入 finally语句,执行其中的代码块当try块中的程序打开了一些物理资源(文件、数据库连接等)时,由于这些资源必须手动回收,回收工作通常就放在finally块中Python垃圾回收机制只能回收变量、类对象占用的内存,无法自动完成关闭文件、数据库连接等这些的工作
try:a = int(input("输入 a 的值:"))print(20/a)
except:print("发生异常")
else:print("执行 else 块中的代码")
finally :print("执行 finally 块中的代码")
输入 a 的值:a
发生异常
执行 finally 块中的代码
当try块发生异常,且没有合适的except处理异常时,finally 块中的代码也会得到执行try:print(20/0)
finally :print("执行 finally 块中的代码")
执行 finally 块中的代码
ZeroDivisionError: division by zero当try块中代码发生异常,在程序崩溃前Python解释器也会执行finally块中的代码

四.获取异常信息

sys.exc_info()

exc_info()会将当前的异常信息以元组的形式返回,该元组中包含 3 个元素,为 type、value 和 tracebacktype:异常类型的名称,是BaseException的子类
value:捕获到的异常实例
traceback:一个traceback对象
import sys   #引入sys模块
try:x = int(input("输入一个被除数:"))print("30除以",x,"等于",30/x)
except:print(sys.exc_info())print("其他异常")
输入一个被除数:0
(<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero',), <traceback object at 0x02B5FFA8>)
其他异常第 1 个元素是一个ZeroDivisionError 类
第 2 个元素是异常类型 ZeroDivisionError 类的一个实例
第 3 个元素为一个 traceback 对象通过前2个元素可以看出抛出的异常类型以及描述信息,第 3 个元素是一个 traceback 对象,无法直接看出有关异常的信息,还需要对其做进一步处理

traceback模块

traceback模块可以用来查看异常的传播轨迹,追踪异常触发的源头在实际应用程序的开发中,一个大的功能需要由多个函数或方法来共同实现,在最终编程模型中,很多对象将通过一系列函数或方法调用来实现通信,执行任务当应用程序运行时,经常会发生一系列函数或方法调用,异常的传播则相反,只要异常没有被完全捕获(异常没有被捕获,或者异常被处理后重新引发了新异常)
异常就从发生异常的函数或方法逐渐向外传播,先传给该函数或方法的调用者,该函数或方法的调用者再传给其调用者,最后传到解释器,此时解释器会中止该程序,并打印异常的传播轨迹信息
用traceback模块查看异常传播轨迹,首先将 traceback 模块引入,提供了两个常用方法:traceback.print_exc():将异常传播轨迹信息输出到控制台或指定文件中format_exc():将异常传播轨迹信息转换成字符串常用的 print_exc() 是 print_exc([limit[, file]]) 省略了 limit、file 两个参数的形式print_exc([limit[, file]]) 的完整形式是 print_exception(etype, value, tb[,limit[, file]])etype:指定异常类型
value:指定异常值
tb:指定异常的traceback 信息print_exc([limit[, file]]) 相当于如下形式:
print_exception(sys.exc_etype, sys.exc_value, sys.exc_tb[, limit[, file]])print_exc([limit[, file]]) 会自动处理当前 except 块所捕获的异常limit:用于限制显示异常传播的层数,比如函数 A 调用函数 B,函数 B 发生了异常,如果指定 limit=1,只显示函数 A 里面发生的异常,如果不设置则默认全部显示
file:指定将异常传播轨迹信息输出到指定文件中,如果不指定该参数,则默认输出到控制台
import traceback # 导入trackback模块
class SelfException(Exception): pass
def main():firstMethod()
def firstMethod():secondMethod()
def secondMethod():thirdMethod()
def thirdMethod():raise SelfException("自定义异常信息")
try:main()
except:traceback.print_exc()     # 捕捉异常,并将异常传播信息输出控制台traceback.print_exc(file=open('log.txt', 'a'))     # 捕捉异常,并将异常传播信息输出指定文件中先导入traceback模块,接下来使用except捕获程序的异常,并使用traceback 的 print_exc() 方法输出异常传播信息,将它输出到控制台和指定文件中运行上面程序,可以看到在控制台输出异常传播信息,在程序目录下生成了一个 log.txt 文件,该文件中同样记录了异常传播信息

五.raise语句

使用raise语句在程序中手动设置异常raise [exceptionName [(reason)]]用[]括起来的为可选参数,其作用是指定抛出的异常名称,以及异常信息的相关描述。如果可选参数全部省略,则 raise 会把当前错误原样抛出;如果仅省略 (reason),则在抛出异常时,将不附带任何的异常描述信息raise 语句三种常用用法:raise:单独一个raise引发当前上下文中捕获的异常(比如except 块中)或默认引发 RuntimeError 异常raise 异常类名称:raise 后带一个异常类名称,表示引发执行类型的异常raise 异常类名称(描述信息):在引发指定类型的异常的同时,附带异常的描述信息
raise 语句引发的异常通常用 try except(else finally)异常处理结构来捕获并进行处理try:a = input("输入一个数:")if(not a.isdigit()):     #判断输入的是否为数字raise ValueError("a 必须是数字")
except ValueError as e:print("引发异常:",repr(e))
输入一个数:a
引发异常: ValueError('a 必须是数字',)当输入的不是数字时,进入 if 判断语句,并执行 raise 引发 ValueError 异常,因为其位于 try 块中,raise抛出的异常会被try捕获,并由except块进行处理虽然程序中使用了 raise 语句引发异常,但程序的执行是正常的,手动抛出的异常并不会导致程序崩溃
使用 raise 语句时可以不带参数try:a = input("输入一个数:")if(not a.isdigit()):    #判断输入的是否为数字raise ValueError("a 必须是数字")
except ValueError as e:print("引发异常:",repr(e))raise位于except块中的 raise,在之前已经手动引发了 ValueError 异常,这里再使用 raise 语句时,会再次引发一次try:a = input("输入一个数:")if(not a.isdigit()): #判断输入的是否为数字raise
except RuntimeError as e:print("引发异常:",repr(e))
输入一个数:a
引发异常: RuntimeError('No active exception to reraise',)在没有引发过异常的程序使用无参的 raise 语句,默认引发的是 RuntimeError 异常

六.异常处理机制的正确使用

不要使用异常处理来代替正常的业务逻辑判断

异常处理机制的初衷是将不可预期异常的处理代码和正常的业务逻辑处理代码分离

不要过度使用异常过度使用异常1.把异常和普通错误混淆在一起,不编写任何错误处理代码,以简单地引发异常来代替所有的错误处理2.使用异常处理来代替流程控制异常只应该用于处理非正常的情况,不要使用异常处理来代替正常的流程控制对于可预知,而且处理方式清楚的错误,程序应该提供相应的错误处理代码,而不是将其笼统地称为异常
不要使用过于庞大的 try 块try 块里的代码过于庞大,会造成 try 块中出现异常的可能性大大增加,从而导致分析异常原因的难度也大大增加在同一个 try 块后紧跟大量的 except 块需要分析它们之间的逻辑关系,增加了编程复杂度正确的做法是把庞大的 try 块分割成多个可能出现异常的程序段落,并把它们放在单独的 try 块中,从而分别捕获并处理异常
不要忽略捕获到的异常己捕获到异常,应及处理并修复异常处理异常,对异常进行合适的修复,绕过异常发生的地方继续运行……程序应该尽量修复异常,使程序能恢复运行重新引发新异常,把在当前运行环境下能做的事情尽量做完,然后进行异常转译,把异常包装成当前层的异常,重新传给上层调用者如果当前层不清楚如何处理异常,不要在当前层使用 except 语句来捕获该异常,让上层调用者来负责处理该异常

Python学习笔记(十三):异常处理机制相关推荐

  1. 【Python学习笔记】异常处理try-except

    Python异常处理 我们一般使用try-except语句来进行异常处理. 使用except Exception as err可以统一捕捉所有异常,而也可以分开处理单个异常. # 分开捕捉单个异常tr ...

  2. 前阿里大佬干货分享,0基础小白,转行必看Python学习笔记(七)

    Python学习笔记7 异常处理 包和模块 包和模块的一般操作 导入操作的本质 模块检索的路径 导入模块的场景 第三方包和模块的安装 异常处理 系统内部一开始已经内置了一些特定的错误场景,当我们触发了 ...

  3. Python学习笔记之类型判断,异常处理,终止程序操作小结

    Python学习笔记之类型判断,异常处理,终止程序操作小结 运行结果: 这里有我自己整理了一套最新的python系统学习教程,包括从基础的python脚本到web开发. 爬虫.数据分析.数据可视化.机 ...

  4. Python学习笔记(十三)

    Python学习笔记(十三): 模块 包 if name == main 软件目录结构规范 作业-ATM+购物商城程序 1. 模块 1. 模块导入方法 import 语句 import module1 ...

  5. Python学习笔记:第十三站 接着找对象

    Python学习笔记 文章目录 Python学习笔记 第十三站 接着找对象 1. 封装 2. 继承 3. 方法重写 4. object类 5. 多态 6. 特殊方法和特殊属性 7. 类的赋值与拷贝 8 ...

  6. Python学习笔记16:实操案例十三(编写程序实现乐手弹奏乐器,设计自定义类表达出租车和家用轿车信息)

    Python学习笔记16:实操案例十三(编写程序实现乐手弹奏乐器,设计自定义类表达出租车和家用轿车信息) 1.编写程序实现乐手弹奏乐器 注意Python的多态是"鸭子类型",只要有 ...

  7. python学习笔记,初学者Python3

    Python学习笔记 不推荐将python作为主力语言,但推荐作为一个辅助语言,用于日常的一些小的任务 python目前主要的应用场景: 1.机器学习,人工智能 2.爬虫 3.数据分析 4.自动化,运 ...

  8. Python 学习笔记——Code with mosh课程

    Python 学习笔记--Code with mash II- Python Basics 1- Variables 2- Dynamic Typing 3- Type Annotation(注释) ...

  9. Python学习笔记:第十一站 全民来找茬

    Python学习笔记 文章目录 Python学习笔记 第十一站 全民来找茬 1. Bug的由来及分类 2. 不同异常类型的处理方式 3. 异常处理机制 4. PyCharm的调试模式 5. 本章作业 ...

最新文章

  1. Codeforces 825E - Minimal Labels
  2. Linux常用命令汇总--ln
  3. java右移位_java中的左移 右移
  4. java win10 通知_如何在Java中创建Windows通知
  5. 【转】EL表达式 (详解) .
  6. 【Redis学习笔记】2018-06-14 Redis源码学习之sentinel
  7. iOS核心动画高级技术(九) 图层时间
  8. Windows 系统环境变量大全
  9. matlab做叠加定理仿真,实验一 仿真软件的使用与叠加原理的验证
  10. 获取微信所有聊天记录数据并通过Python制作词云图
  11. deprecated注释 原因
  12. 室内定位系列(一)——WiFi位置指纹(译)
  13. 活动策划书用什么计算机软件,各行业主流设计软件有哪些?(设计人员请进)...
  14. 干货 | 这可能是最详细的「阻抗匹配」介绍
  15. 基于MMRotate训练自定义数据集 做旋转目标检测 2022-3-30
  16. linux内核软盘,软盘也成为历史文物了:Linux内核也将取消软盘驱动器的支持
  17. 宿州市空间数据库管理系统(2)
  18. mybatis XML 中<if>、<choose>、<when>、<otherwise>等标签的使用?多条件查询该怎么处理?
  19. 关于flask入门教程-自定义弹出框
  20. UVALive - LED Circuit(Spfa)

热门文章

  1. 干货 | 深度学习之卷积神经网络(CNN)的模型结构
  2. Potplayer关闭播放时的信息
  3. Android Studio使用签名打包发布APP(安卓生成apk文件)
  4. ubuntu 复制文件夹到另一目录命令
  5. 100行代码实现数字滚动抽奖功能
  6. 数据项、数据字典、模式等基本概念辨析 数据库系统结构
  7. win7试用期过后不激活的后果
  8. MongoDB迁移方案
  9. SQL难学吗,有什么好的学习建议?
  10. 谈谈Http长连接和Keep-Alive以及Tcp的Keepalive