版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第13章
异常处理异常(exception)简单地说,异常是指程序运行时引发的错误。引发错误的原因有很多,例如除零、下标越界、文件不存在、网络异常、类型错误、名字错误、字典键错误、磁盘空间不足等等。如果这些错误得不到正确的处理将会导致程序终止运行,而合理地使用异常处理结果可以使得程序更加健壮,具有更强的容错性,不会因为用户不小心的错误输入或其他运行时原因而造成程序终止。也可以使用异常处理为用户提供更加友好的提示。程序出现异常或错误之后是否能够调试程序并快速定位和解决存在的问题也是程序员综合水平和能力的重要体现方式之一。13.1异常词法分析语法分析字节码运行类型检查内存管理可能的错误语法错误对齐不正确可能的错误变量不存在下标不存在文件不存在…可能的错误类型不正确OOM:内存溢出…什么是异常语法错误和逻辑错误不属于异常,但有些语法错误往往会导致异常,例如由于大小写拼写错误而访问不存在的对象。当Python检测到一个错误时,解释器就会指出当前无法继续执行下去,这时候就出现了异常。异常是指因为程序出错而在正常控制流以外采取的行为。异常分两阶段:第一阶段是引发异常;第二阶段是检测并处理异常。不建议使用异常来代替常规的检查,如if...else判断。当程序出现错误,python会自动引发异常,也可以通过raise引发异常。13.2Python常见异常类下表列出了常用的异常类异常类的使用异常类有两种使用方式异常处理语句(13.3)
通过使用try…catch…else…finally的形式,控制异常发生以及处理的过程,从而增强程序的健壮性。引发异常(13.5)
在检测到函数参数或者程序状态处于非正常的情况下,可以通过raise语句,引发异常。13.3异常处理Python异常处理由try语句实现,语法形式如下上面是计算机中用于描述语言的语法,使用了特殊的符号try语句分为两类,分别是上面的try1和try2异常处理语句。try语句包括try子句、except子句、else子句和finally子句;这些子句具有不同的功能。try_stmt
::=
try1_stmt|try2_stmttry1_stmt
::=
"try"
":"suite
("except"
[expression["as"identifier]]
":"suite)+
["else"
":"suite]
["finally"
":"suite]try2_stmt
::=
"try"
":"suite
"finally"
":"suite语法符号的含义::=表示定义|表示或者[]表示可选()表示作为整体+表示重复≥1次suite
表示语句try子句try子句是必须的,其形式为其中的子句(suite)可以是任意的python语句,在子句的前面必须是try关键字且其后必须是冒号(:)。这些语句放置在try后加以保护。如果运行时语句没有出现异常,那么子句中的所有语句会依次运行,并且不启动异常处理流程;如果运行时语句出现了异常,那么异常点之后的所有try块的语句都不会执行;同时python解释器会生成一个异常对象,后续进入异常处理流程。"try"
":"suiteexcept子句except子句必须在try子句之后,其形式为except子句由一个以上(上面的+表示)的例外处理句柄构成。例外处理句柄由关键字except开头,包含可选的表达式或表达式as标识符两种形式。通常表达式由内置的异常类或用户自定义的异常类表示。在冒号(:)之后是处理句柄的语句(suite)。通常例外处理句柄有以下三种形式handler::="except"
[expression["as"identifier]]
":"
suite(handler)+except
NameError
ase:passexcept
NameError:passexcept:pass通配符except子句except子句的执行except子句处理规则1)如果try子句没有产生异常,则except子句不执行。如果后续有else子句,则转去执行else子句。2)如果try子句产生了异常,则python解释器将查找与当前异常对象匹配的异常处理句柄。匹配会从第一个异常处理句柄开始,直到找到匹配的异常处理句柄,或者直到except子句结束仍未找到匹配的异常处理句柄。带有表达式的异常处理句柄会被求值,若计算的结果与引发的异常”类型兼容”,则该异常处理句柄匹配该异常。类型兼容是指结果对象是该异常对象所属类或其基类;或者结果对象包含异常对象所属类或其基类的元组。没有表达式的异常处理句柄(通配符处理句柄),可以匹配任意的异常。因此这种异常处理句柄通常会放在except子句的结尾。找到匹配的异常处理句柄之后,python解释器会执行该句柄。不管有没有找到匹配的异常处理句柄,如果后续有finally子句,则转去执行finally子句。else子句else子句是可选的且只能有一个,其形式为else子句处理规则1)当try语句执行完且没有引发异常,并且try语句中并不包含break、continue或return语句时,else语句会被执行;否则,else语句将不会被执行。2)如果else语句中又引发了新的异常,这个异常不会被前面的try语句捕获!"else"
":"suitefinally子句finally子句是可选的且只能有一个,且必须放在try语句的最后,其形式为finally子句处理规则1)不管try子句有没有引发异常,finally子句一定会被执行。因此,通常会在finally子句中定义资源清理功能。2)无论try子句中是否包含return、break或continue语句,finally子句在离开时都会执行。3)在到达finally子句时,如果存在未被处理的异常对象(例如try语句引发了异常,但是没有找到匹配的异常处理句柄),该异常对象会被暂存。在finally子句的末尾会重新引发该暂存的异常;如果finally子句又引发了新异常,被暂存的异常会称为新异常的上下文;如果finally子句执行了return、break或continue语句,暂存的异常对象会被丢弃。"finally"
":"suite异常处理示例(1)例2
分析下面的输出结果bar函数中的try…finally形式是第2中形式的异常处理。try子句不会引发异常;finally子句和try子句中都包含return语句;函数的返回值由finally子句中的return语句决定。因此最后的返回值为“finally”。>>>defbar():...try:...return'try'...finally:...return'finally'
>>>print(bar)异常处理示例(2)例3
分析下面的输出结果foo函数中的try子句引发了ZeroDivisionError异常finally子句包含return语句,因此抑制了try子句中的异常;函数的返回值为2024;因此程序的输出为”2024”。>>>deffoo():...try:...1/0...finally:...return2024>>>foo()异常处理示例(3)例4分析下面的输出结果foobar函数中的try子句引发了ZeroDivisionError异常,通配符异常处理句柄匹配该异常,同时又引发了新异常ValueErrorfinally子句包含return语句,因此抑制了try子句中的异常;函数的返回值为2024;因此程序的输出为”2024”。>>>deffoobar():...try:...1/0...except:...raiseValueError...finally:...return2024>>>foobar()异常处理示例(4)例5
读模式访问文件try:f=open("data.txt",mode="rt")#1print(f.readlines())#2exceptFileNotFoundErroraserror:print(error.args[1])#3exceptOSErroraserror:print(error.args)#4finally:f.close()#5√√√文件存在且具有读访问权限文件不存在√√√×文件存在且没有读访问权限√√√×(13,'Permissiondenied')NameError:name'f'isnotdefinedNosuchfileordirectoryNameError:name'f'isnotdefined没有输出异常处理示例(5)例6读模式访问文件,忽略某些异常。try:
f=open("data.txt",mode="rt")#1print(f.readlines())#2f.close()except(FileNotFoundError,PermissionError):
pass
#3上面的代码在异常处理句柄中使用了pass语句;使用了元组匹配多种异常。这样使得最终这两种异常都会被忽略。13.5引发异常主动引发异常使用内置异常类;或使用自定义异常类。引发异常使用raise关键字,其语法形式如下expression:是一个异常类,或异常类的实例;another_expression:是另外一个异常类,或异常类的实例。上面的语法形式表示了三种形式的raise语句raise[expression
[fromanother_expression]]
raise
#1raiseexpression
#2raiseexpressionfrom
another_expression#31)不带参数引发异常不带参数引发异常,形式如下这种形式主要用于重新引发正在处理的异常:正在处理的异常通常称为活动异常。try子句中引发的异常,如果有匹配的异常处理句柄,在处理完毕之后,该异常对象会被销毁。某些情况下,需要保留该异常对象,此时可以使用不带参数引发异常。raise
#1importloggingtry:2024/0exceptExceptionaserror:logging.error(error)
raise例7在代码出现异常的情况下,记录异常的信息,且不影响该异常的正常处理。代码分析:在异常处理句柄中,使用Exception类捕获了多数异常;同时,使用raise语句重新引发已处理的异常。2)带表达式的引发异常带表达式的引发异常形式如下这种形式主要用于引发异常的一般形式;在处理异常过程中重新引发原有异常,或在程序的任意位置引发新异常;表达式必须是BaseException类或其子类的实例。raiseexpression#1例8根据要求引发新异常。代码分析:函数divide对参数a和b进行了检查;如果a和b的类型不是int类型,引发TypeError异常;如果b为0值,引发ValueError异常。defdivide(a,b):ifnot(type(a)==intandtype(b)==int):raiseTypeError("除数和被除数应该是整数")ifb==0:raiseValueError("被除数为0")returna//b2)带表达式的引发异常例9把例7的代码更改为raiseerror。代码分析:代码功能和例7是一样的。importloggingtry:2024/0exceptExceptionaserror:logging.error(error)
raise
error3)带from子句引发异常带from子句引发异常语法形式如下这种形式引发异常的作用包括:抑制链式异常或指明异常产生的原因。抑制异常:把例7的代码更改为raiseValueError("")fromNone。代码分析:代码功能和例7类似的;但是指明None,则实际上抑制了异常;避免了链式异常可能出现的大量信息。importloggingtry:2024/0exceptExceptionaserror:logging.error(error)
raiseValueError("")fromNoneraiseexpressionfromanother_expression#3自定义异常类下面的例子演示了自定义的异常类必须继承Exception类:所有异常类的基类;class
GradeValueError(Exception):
passdef
reckon_average_grade(grades):
total,count=
0,0
forgradeingrades:
ifgrade<
0
orgrade>
100:
raiseGradeValueError("分数须在[0,100]之间")
total,count=total+grade,count+1
return
round(total/count,2)>>>reckon_average_grade([98,87,110])Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
File"<stdin>",line8,incalculate_average_gradeGradeValueError:分数须在[0,100]之间命名约定:自定义异常类使用大写的骆峰命名;如果是错误,则命名的最后部分附加单词Error;如果是警告,则命名的最后部分附加单词Warning。13.6异常处理方式处理异常的两种方式预防式策略防止错误或者异常的产生;通过条件语句来实现;没有异常处理机制的语言常用这种策略。处理式策略放任错误或异常的发生,然后使用异常处理机制;提供了异常处理机制的语言常用这种策略;python中没有没有引发异常时,异常处理的开销小,因此鼓励使用处理式策略。策略的比较例10编写函数char_frequency,对于给定的文本统计字符的出现频度。def
char_frequency_pre(text):
counter={}
forcharintext:
ifcharnot
incounter.keys():
counter[char]=
1
else:
counter[char]+=
1
returncounterdef
char_frequency_post(text):
counter={}
forcharintext:
try:
counter[char]+=
1
except
KeyError:
counter[char]=
1
returncounter预防式策略处理式策略处理时间短编码简单策略的比较例11编写函数convert_int(s),把字符串形式的数值转换成整数。预防式策略处理式策略处理时间短编码简单def
convert_int(s):
assert
isinstance(s,str),"参数s应当是str类型"
ifis_int(s):
return
int(s)
return
Nonedef
convert_int(s):
assert
isinstance(s,str),"参数s应当是str类型"
try:
return
int(s)
except
ValueError:
return
Nonedef
is_int(s):
s=s.strip()
ifs[0:1]in
'+-':
s=s[1:]
returns!=''
ands.isdigit()13.7断言断言用于应用程序和软件的开发过程中设置健全性检查的语句允许在代码中检查某些条件的正确性从而测试代码的正确性断言的语法为上面的断言与下面的语句功能一致断言工作机制当__debug__为假时,该语句无作用;当__debug__为真且检查的条件为真时,该语句同样无作用;当__debug__为真且检查的条件为假时,该语句起作用,会引发AssertionError,可选的参数说明了AssertionError异常产生的原因。assert
expression[,message]if
__debug__:
if
notexpression:
raise
AssertionError([message])断言作用断言作用:用于验证函数的前置或后置条件;或者函数的状态;或者进行代码的测试。例12编写函数计算圆的面积。frommathimportpidef
area(r
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年版网红直播间电商合作合同三篇
- 962生产建设项目定期进行职业病危害因素安全检测和控制效果现状评价及其时间阶段分析说明2026.7.22.4
- 老年人护理技术与应用创新
- 2026年供应室职业安全管理与防护
- 佛山市2025广东佛山市三水区业余体育学校事业单位人员招聘3人笔试历年参考题库典型考点附带答案详解
- 云浮市2025广东云浮市招募就业见习人员291人笔试历年参考题库典型考点附带答案详解
- 云南省2025云南滇西应用技术大学招聘57人笔试历年参考题库典型考点附带答案详解
- 云南省2024云南保山市生态环境工程评估中心招聘(6人)笔试历年参考题库典型考点附带答案详解
- 临湘市2025湖南岳阳临湘市场监督管理局下属单位招20人笔试历年参考题库典型考点附带答案详解
- 东台市2025江苏盐城市东台市农业农村局聘劳务派遣人员2人笔试历年参考题库典型考点附带答案详解
- 成都未来科技城发展服务局2026年社会招聘笔试题库附参考答案详解【模拟题】
- 烧结多孔砖生产施工方案及技术措施
- 山东能源定向委培考试题
- 2025广东省风力发电有限公司山西分公司招聘7人笔试历年难易错考点试卷带答案解析
- 骨科疾病常见诊疗常规
- 2025年四川省省级机关公开遴选考试真题(附答案)
- 2026版中央安全生产考核巡查明查暗访应知应会
- GD2016《2016典管》火力发电厂汽水管道零件及部件典型设计(取替GD2000)-401-500
- 高考英语时态专项练习题汇编
- 天津市第一中心医院招聘考试真题2024
- 雨课堂学堂在线学堂云《船舶柴油机装配与调试(渤海船舶职院 )》单元测试考核答案
评论
0/150
提交评论