python实用教程-第九章-异常处理

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第九章异常处理•前面章节很多程序的执行中,经常会碰到程序执行过程中没有得到预期结果的情况。对于程序运行过程中出现的不正常,有时称为错误,有时称为异常,也有时说程序没有按预期运行,从本章开始将有一个统一的称谓——异常。•本章将带领读者学习如何处理各种异常,以及创建和自定义异常。•Python快乐学习班的同学参观完对象动物园后,由导游带领来到了异常过山车入口。此处的异常过山车坐起来非常刺激,乘坐异常过山车的过程中,过山车随时都可能停下来,有一些是正常的停止,也会有一些在未预知的情况下停止,但只要过山车上的乘客发挥自己的聪明才智,就有办法让停止的过山车动起来。听起来很刺激吧,现在开始开启异常过山车之旅。9.1异常定义•在本节开始之前,先看看如下程序:•print(hello,world)•Traceback(mostrecentcalllast):•Filepyshell#12,line1,inmodule•print(hello,world)•NameError:name'hello'isnotdefined•对于Python初学者,在Python的学习过程中,当编写的代码执行时,经常会遇到程序执行报错的问题,使程序不能得到预期结果,如NameError、SyntaxError、TypeError、ValueError等,这些都是异常。•这节我们会专门介绍异常。•异常是一个事件,该事件会在程序执行过程中发生,影响程序的正常执行。一般情况下,在Python无法正常处理程序时就会发生异常。•异常是Python的对象,表示一个错误。当Python脚本发生异常时,需要捕获并处理所有异常,否则程序会终止执行。就如乘坐过山车,有任何让过山车在运行过程中停下的异常因素都需要排除,否则难以保证乘客的安全。•在Python中,异常属于类的实例,这些实例可以被引用,并且可以用很多种方法进行捕捉,使得异常可以用一些友好的方式进行化解,而不是简单粗暴的让整个程序停止。9.2异常化解•出了异常怎么办呢?•就如乘坐的异常过山车,当在运行过程中停止时,乘客可以通过自己的才智让过山车运行起来。•程序也一样,作为程序开发人员,谁都不想让自己写出来的代码有问题,但这几乎是不可能的。好在编写程序的前辈们经过不断积累与思考,创造了不少好方法处理程序中的异常,Python中,异常最简单的化解方式是使用try语句。•try语句的语法格式如下:•try:•语句#运行别的代码•except名字:•语句#如果在try部份引发了异常•try语句的工作原理是,开始一个try语句后,Python就在当前程序的上下文中做标记,当出现异常时就可以回到做标记的地方。•如果当try后的语句执行时发生异常,程序就跳回到try并执行except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。如果不想在发生异常时结束程序,只需在try语句块中捕获异常即可。•defexp_exception(x,y):•try:•a=x/y•print('a=',a)•returna•exceptException:•print('程序出现异常,异常信息:被除数为0')••exp_exception(2,0)•程序在执行过程中,try语句块中的语句在执行时发生异常,程序最后执行的是except子句。因为如果语句正常,应该输出“a=”的形式,但实际输出的是except子句中的打印语句的内容。•在程序执行过程中,如果没有将异常化解,异常就会被“传播”到调用的函数中。如果在调用的函数中依然没有化解异常,异常就会继续“传播”,直到程序的最顶层。•在实际应用中,经常会遇到需要处理多个异常的情况,对于多个异常该怎么化解呢?•Python支持在一个try/except语句中处理多个异常,语法格式如下:•try:•语句#运行别的代码•except名字1:•语句#如果在try部分引发了name1异常•except名字2,数据:•语句#如果引发了name2异常,获得附加数据•try语句按照如下方式工作:•首先执行try子句(在关键字try和关键字except之间的语句);如果try子句执行没有发生异常,忽略except子句,try子句执行后结束;如果在执行try子句的过程中发生异常,try子句余下的部分就会被忽略;如果异常的类型和except之后的名称相符,对应的except子句就会被执行,最后执行try语句之后的代码。如果抛出的异常没有与任何except匹配,那这个异常就会传递到上层的try语句中。一个try语句可能包含多个except子句,分别处理不同的异常,但最多只有一个分支会被执行。•处理程序只针对对应try子句中的异常进行处理,而不会处理其他异常语句中的异常。9.3抛出异常•Python使用raise语句抛出一个指定的异常。我们可以使用一个类(应该是Exception的子类)或者实例参数调用raise语句来引发异常。使用类时,程序会自动创建实例。•如果你只想知道这是否抛出了一个异常,并不想去处理它,那使用一个简单的raise语句就可以再次把它抛出。如下示例:•try:•raiseNameError('ThisisNameError')•exceptNameError:•print('Anexceptionhappened!')#后面不加raise••Anexceptionhappened!#若不加raise,输出对应字符就结束•try:•raiseNameError('ThisisNameError')•exceptNameError:•print('Anexceptionhappened!')•raise#最后加一个raise••Anexceptionhappened!•Traceback(mostrecentcalllast):•Filestdin,line2,inmodule•NameError:ThisisNameError•在实际应用过程中,可以借助raise语句得到更详尽的异常信息。•面碰到的如NameError、SyntaxError、TypeError、ValueError这些异常类称为内建异常类。在Python中,内建的异常类有很多,可以使用dir函数列出异常类的内容(有兴趣可以尝试看看),并且都可以用在raise语句中,用法如raiseNameError这般使用。下表描述了一些重要的内建异常类。异常名称描述Exception常规错误的基类AttributeError对象没有这个属性IOError输入/输出操作失败IndexError序列中没有此索引(index)KeyError映射中没有这个键NameError未声明/初始化对象(没有属性)SyntaxErrorPython语法错误SystemError一般的解释器系统错误ValueError传入无效的参数9.4一个块捕捉多个异常•上一节我们讲述的是一个try语句对应多个except子句,假若需要一个try对应一个except子句,同时捕捉到一个以上的异常。看如下示例:•defmodel_exception(x,y):•try:•b=name•a=x/y•except(ZeroDivisionError,NameError,TypeError):•print('oneofZeroDivisionErrororNameErrororTypeErrorhappened')••model_exception(2,0)•如果需要一个块捕捉多个类型异常,可以将他们作为元组列出。•程序输出结果如下:•oneofZeroDivisionErrororNameErrororTypeErrorhappened•由输出结果可以看到,在一个try对应一个except子句时,若将多个异常放置于一个元组中,能做到捕获一个以上的异常。使用这种方式时,只要遇到的异常类型是元组中的任意一个,都会进入异常流程。•这么做有什么好处呢?•假如希望多个except子句输出同样的信息,就没有必要使一个try语句对应多个except语句,将多个except的异常类放到一个except的元组中即可。9.5异常对象捕捉•如果希望在except子句中访问异常对象本身,也就是看到一个异常对象真正的异常信息,而不是打印出自己定义的异常信息,可以使用ase的形式,称为捕捉对象。示例如下(model_exception_1.py):•defmodel_exception(x,y):•try:•b=name•a=x/y•except(ZeroDivisionError,NameError,TypeError)ase:•print(e)••model_exception(2,0)•看如下示例(model_exception_2.py):•defmodel_exception(x,y):•try:•a=x/y•b=name•except(ZeroDivisionError,NameError,TypeError)ase:•print(e)••model_exception(2,'')•在该示例中,调用函数时有一个实参传入的是空值。输出结果如下:•unsupportedoperandtype(s)for/:'int'and'str'•在实际编码过程中,即使程序能处理好几种类型的异常,但有一些异常还是会从我们手掌中溜走。上面示例中的异常就逃过了try/except语句的检查,对于这种情况根本无法预测会发生什么,也无法提前做任何准备。在这种情况下,与其使用不是捕捉异常的try/except语句隐藏异常,不如让程序立即崩溃。•对于这样的异常,该用什么方式来化解?•示例如下(model_exception_3.py):•defmodel_exception(x,y):•try:•b=name•a=x/y•except:•print('Errorhappened')••model_exception(2,'')•可以在except子句中忽略所有异常类,从而让程序输出自己定义的异常信息。•这里只是给出了一种可参考的解决方式。从实用性方面来讲,不建议这么做,因为这样捕捉异常非常危险,会隐藏所有没有预先想到的错误。•建议在实际应用中,使用抛出异常的方式处理,或者对异常对象e进行一些检查。9.6丰富的else子句•异常为我们提供了try....except...else的语句来实现该功能,其语法如下:•try:•语句#运行别的代码•except名字:•语句#如果在try部份引发了异常1•except名字,数据:•语句#如果引发了异常2,获得附加的数据•else:•语句#如果没有异常发生•如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话)。使用else子句比把所有的语句都放在try子句里面要好,这样可以避免一些意想不到的而except又没有捕获的异常。如下示例(model_exception_4.py):•defmodel_exception(x,y):•try:•a=x/y•except:•print('发生异常,走的是except逻辑。')•else:•print('没有发生异常,走的是else逻辑。')••model_exception(2,1)#model_exception函数调用•当程序没有发生异常时,通过添加一个else子句来做一些事情是很有用的,它可以帮助我们更好的判断程序的执行情况。9.7自定义异常•尽管内建异常类包括了大部分异常,也可以满足很多要求,但有一些情况还是需要创建自己的异常类才能处理。比如,若需要精确知道问题的根源,就需要使用自定义异常来精确定位问题。•可以通过创建一个新exception类拥有自己的异常。异常应该继承自Exception类,可以直接继承,也可以间接继承。•错误就是类,捕获一个错误就是捕获该类的一个实例,

1 / 27
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功