No.12、异常

Python的进阶之路

No.12、异常

在生活中,使用计算机中的某个应用软件时,由于某种错误,可能会引发异常,如图所示。
在这里插入图片描述
在程序中,当Python检测到一个错误时,解释器就会指出当前流程已无法继续执行下去,这时就出现了异常。例如,使用print()函数输出一个未定义的变量值,具体如下所示:
在这里插入图片描述
在Python程序中,如果出现异常,而异常对象并未被捕获或处理,程序就会用自动回溯,返回一种错误信息,并终止执行,上述语句返回的错误信息如下:
在这里插入图片描述
上述信息提示name变量名未定义,NameError为Python的内建异常类。异常是指因为程序出错而在正常控制流以外采取的行为,即异常是一个事件,该事件可能会在程序执行过程中发生并影响程序的正常执行。

异常类:
Python为了区分不同的异常,其中内置了许多异常类,常见的异常类如表所示。
在这里插入图片描述
在这里插入图片描述

在表中,BaseException是异常的顶级类,但用户定义的类不能直接继承这个类,而是要继承Exception。Exception类是与应用相关异常的顶层基类,除了系统退出事件类(SystemExit、KeyboardInterrupt和GeneratorExit)之外,几乎所有用户定义的类都应该继承自这个类,而不是BaseException类。

捕获与处理异常
为了防止程序运行中遇到异常而意外终止,开发时应对可能出现的异常进行捕获并处理。Python程序使用try、except、else、finally这4个关键字来实现异常的捕获与处理。

try-except语句:
try-except语句可以捕获异常并进行处理,其语法格式如下:
在这里插入图片描述
当try语句块中某条语句出现异常时,程序就不再执行try语句块中后面的语句,而是直接执行except语句块,如例所示。

try:
	a = float(input('请输入被除数:'))
	b = float(input('请输入除数:'))
	print(a,'/',b,'结果为',a/b)
	print('运算结束')
except ZeroDivisionError:
	print('除数不能为0')
print('程序结束')

需要注意的是,上例程序只能捕捉except后面的异常类,如果发生其他类型异常,程序依然会终止。例如,运行上例程序,输入ab再回车,则程序出现错误,如图所示。
在这里插入图片描述
在图中,错误信息提示字符串类型不能转化为浮点型。为了保证程序正常运行,此时就需要捕获并处理多种异常,其语法格式如下:
在这里插入图片描述
在程序中,虽然开发者可以编写处理多种异常的代码,但异常是防不胜防的,很有可能再出现其他异常,此时就需要捕获并处理所有可能发生的异常,其语法格式如下:
在这里插入图片描述
如果程序发生了异常,但是没有找到匹配的异常类别,则执行不带任何匹配类型的except语句块。

使用as获取异常信息
为了区分不同的异常,可以使用as关键字来获取异常信息,其语法格式如下:
在这里插入图片描述
如果程序需要获取多种异常信息,则可以使用如下语法格式:
在这里插入图片描述
如果程序需要获取所有异常信息,则可以使用如下语法格式:
在这里插入图片描述
所有的异常类都继承自BaseException类,因此上述语句可以获取所有异常信息。

try-except-else语句:
try-except-else语句用于处理未捕获到异常的情形,其语法格式如下:
在这里插入图片描述
如果try语句内出现了异常,则执行except语句块,否则执行else语句块。
接下来演示try-except-else语句的用法,如例所示。
在这里插入图片描述
try-finally语句
在try-finally语句中,无论try语句块中是否发生异常,finally语句块中的代码都会执行,其语法格式如下:
在这里插入图片描述
其中,finally语句块用于清理在try块中执行的操作,如释放其占有的资源(如文件对象、数据库连接、图形句柄等)。
另外,with-as语句可作为try-finally语句处理异常的替代,其语法格式如下:
在这里插入图片描述
该语句用于定义一个有终止或清理行为的情况,如释放线程资源、文件、数据库连接等,在这些场合下使用with语句将使代码更加简洁。

在讲解文件打开与关闭时,本书使用的就是with-as语句。with后面的表达式的结果将生成一个支持环境管理协议的对象,该对象中定义了__enter__() 和__exit__()方法。在with内部的语句块执行之前调用__enter__()方法运行构造代码,如果在as后面指定了一个变量,则将返回值和这个变量名绑定。当with内部语句块执行结束后,自动调用__exit__()方法,同时执行必要的清理工作,不管执行过程中有无异常发生。

以上学习了try-except语句、try-except-else语句和try-finally语句,在实际开发中,经常需要将3种语句结合起来使用,具体如下所示:
在这里插入图片描述
程序先执行try语句块,若try语句块中的某一语句执行时发生异常,则程序跳转到except语句,从上到下判断抛出的异常是否与except后面的异常类相匹配,并执行第一个匹配该异常的except后面的语句块。
若try语句块中发生了异常,但是没有找到匹配的异常类,则执行不带任何匹配类型的except语句块。
若没有发生任何异常,则程序在执行完try语句块后直接进入else语句块。
最后,无论程序是否发生异常,都会执行finally语句块。

触发异常
触发异常有两种情况:一种是程序执行中因为错误自动触发异常,另一种是显式地使用raise或assert语句手动触发异常。Python捕获与处理这两种异常的方式是相同的。本节主要介绍手动触发异常。

raise语句
raise语句可以手动触发异常,其使用方法有如下3种。

  1. 通过类名触发异常
    该方法只需指明异常类便可创建异常类的实例对象并触发异常,其语法格式如下:
    在这里插入图片描述
    例如,手动触发语法错误异常,则可以使用以下语句:
    在这里插入图片描述
    程序运行时,输出以下信息:
    在这里插入图片描述
  2. 通过异常类的实例对象触发异常
    该方法只需指明异常类的实例对象便可触发异常,其语法格式如下:
    在这里插入图片描述
    例如,手动触发除零导致的异常,则可以使用以下语句:
    在这里插入图片描述
    程序运行时,输出以下信息:
    在这里插入图片描述
    此外,该方法还可以指定异常信息,具体如下所示:
    在这里插入图片描述
    程序运行时,输出以下信息:
    在这里插入图片描述
  3. 重新触发异常
    raise语句还可以重新触发异常,具体如下所示:
    在这里插入图片描述
    程序运行时,输出以下信息:
    在这里插入图片描述
    可以看出,程序执行了except语句块中的代码,其中的raise语句会重新触发ZeroDivisionError异常,但此时异常对象并未被捕获或处理,因此程序终止运行。

assert语句
assert语句(又称断言)是有条件的触发异常,其语法格式如下:
在这里插入图片描述
其中,当表达式为真时,不触发异常;当表达式为假时,触发AssertionError异常。若给定了参数部分,则在AssertionError后将参数部分作为异常信息的一部分给出。
assert语句的主要功能是帮助程序员调试程序,以保证程序运行的正确性,因此它一般在开发调试阶段使用。
接下来演示assert语句的用法,如例所示。
在这里插入图片描述

【自定义异常】
Python中内置的异常类毕竟有限,用户有时须根据需求需设置其他异常,如学生成绩不能为负数、限定密码长度等。自定义异常类一般继承于Exception或其子类,其命名一般以Error或Exception为后缀,如例所示。
在这里插入图片描述
【回溯最后的异常】
当触发异常时,Python可以回溯异常并提示许多信息,这可能会给程序员定位异常位置带来不便,因此,Python中可以使用sys模块中exc_info()函数来回溯最后一次异常信息,该函数返回一个元组(type, value/message, traceback),每个元素的具体含义如下所示:
type:异常的类型。
value/message:异常的信息或者参数。
traceback:包含调用栈信息的对象。
接下来演示该函数的用法,如例所示。
在这里插入图片描述

Good bye!

PS:图片素材来源于网络。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值