查看原文
其他

给妹子讲python-S01E24异常处理方式

给妹子讲python Python爱好者社区 2019-04-07

作者:酱油哥/ 清华程序猿      
微信公众号: python数据科学家
知乎专栏: 《给妹子讲python》
https://zhuanlan.zhihu.com/c_147297848



前文传送门:

给妹子讲python-S01E01好用的列表

给妹子讲python-S01E02学会用字典

给妹子讲python-S01E03元组的使用

给妹子讲python-S01E04容器遍历和列表解析式

给妹子讲python-S01E05字符串的基本用法

给妹子讲python-S01E06字符串用法进阶

给妹子讲python-S01E07字符编码历史观:从ASCII到Unicode

给妹子讲python-S01E08理清python中的字符编码方法

给妹子讲python-S01E09文件操作小意思

给妹子讲python-S01E10动态类型与共享引用

给妹子讲python-S01E11赋值与对象拷贝

给妹子讲python-S01E12循环迭代初体验

给妹子讲python-S01E13循环迭代高级技巧

给妹子讲python-S01E14可迭代对象和迭代器

给妹子讲python-S01E15迭代环境

给妹子讲python-S01E16生成器的使用

给妹子讲python-S01E17函数的基本特征

给妹子讲python-S01E18初探函数作用域

给妹子讲python-S01E19内嵌作用域与函数闭包

给妹子讲python-S01E20函数参数的传递与修改

给妹子讲python-S01E21函数参数的匹配与解包

给妹子讲python-S01E22神奇的装饰器

给妹子讲python-S01E23初识异常

【要点抢先看】

1.try、except、else、finally、raise关键字
2.异常的处理流程
3.try/except/else/finally组成的几种异常处理模式

通过上一节我们知道了python异常的整个框架。本节会详细介绍异常编码的语法模式,try/except/else和try/finally。

先重新回顾一下try、except、else、finally几个关键字:

try后面紧跟着缩进的语句代码,代表此语句的主要动作:试着执行的程序代码。

然后是一个或多个except分句来识别要捕获的异常,except子句内定义try代码块内引发的异常处理器,

最后是一个可选的else分句,提供没发生异常时要执行的语句。

分别讨论下面的几种情形:

如果try代码块语句执行时的确发生了异常,python就跳出try,执行第一个符合引发异常的except子句下面的语句。当except代码块执行结束后,控制权就会到整个try代码块后继续执行。

如果异常发生在try代码块内,没有符合的except子句,异常就会传递到顶层,迫使python终止这个程序并打印默认的出错信息。

如果try首行底下执行的语句没有发生异常,python就会执行else行下的语句,控制权会在整个try语句下继续。

换句话说,except分句会捕获try代码块执行时所发生的异常,而else子句只在try代码块执行时不发生异常才会执行。

except是专注于异常处理器的:捕捉只在相关try代码块中的语句所发生的异常。尽管这样,因为try代码块语句可以调用写在程序其他地方的函数,异常的来源可能在try语句自身之外。

关于except子句的一些说明:

except子句可以用括号列出一组异常[except (e1,e2,e3)],而如果except子句后没有列出异常名称,即except:时,会捕捉所有的异常类型。

但是,空except也会引发一些设计的问题,尽管方便,也可能捕捉和程序代码无关、意料之外的系统异常,而且可能意外拦截其他处理器的异常。例如,在python中,即使是系统离开调用,也会触发异常,而显然你通常会想让这些事件通过。

python引入了一个替代方案来解决这个问题,捕获一个名为Exception的异常,几乎与一个空的except:具有相同的效果,但是忽略和系统退出相关的异常。

来看看try/else语句的作用

也许我们无法一眼看出else子句的用途,不过仔细想想,如果没有else,是无法知道控制流程是否通过了try语句,到底是没有异常引发,还是异常发生了且已被处理过了,不使用else的话很难分得清。

再来分析一下try/finally语句

try中包含了finally子句,python一定会在try语句后执行其语句代码块,无论try代码块执行时是否发生异常。

利用这个变体,python可先执行try首行下的语句代码块。接下来发生的事情,取决于代码块中是否发生异常:

如果try代码块运行时没有异常发生,python会跳至执行finally代码块,然后在整个try语句后继续执行下去。

如果try代码块运行时有异常发生,python依然会回来运行finally代码块,但是接着会把异常向上传递到较高的try语句或顶层的默认异常处理器,程序不会在try语句下继续执行。也就是说,即使发生了异常,finally代码块还是会执行的,和except不同的是,finally不会终止异常,而是在finally代码块执行后,抛出异常。

当想确定某些程序代码执行后,无论程序的异常行为如何,有个动作一定会发生,那么,try/finally形式就很有用。在实际应用中,这可以让你定义一定会发生的清理动作,最直观的就是,在出现异常时,仍能利用finally关闭文件和断开服务器连接。

最后我们来看最完整的形式:try/except/else/finally

try:
    main-action
except Exception1:
    handler1
except Exception2:
    handler2
...
else:
    else-block
finally:
    finally-block

我们从头梳理一遍:

就像往常一样,这个语句中的main-action代码会先执行。如果该程序代码引发异常,那么所有except代码块就会逐一测试,寻找与抛出的异常相符的语句,如果引发的异常是Exception1,就会执行handler1,如果引发的的异常是Exception2,就会执行handler2,以此类推,如果没有引发任何异常,将会执行else-block。而无论之前发生了什么,当main-action代码块完成的时候,而任何引发的异常都已经处理后,finally-block就会执行。事实上,即使异常处理器或者else-block内有错误发生而引发新的异常,finally-block内的程序代码依然会执行。就像之前所说的那样,finally子句并没有终止异常:当finally-block执行的时候,如果异常还存在,就会在finally-block代码块执行后继续传递,而控制权会跳至程序其他地方,如我们的默认的顶层处理器。

最后我们叮嘱一下,try语句必须有一个except或一个finally,else是可选的,但是如果有else,则必须至少有一个except。

最后我们简单的再说说raise

要显式的触发异常,可使用raise语句,其一般形式相当简单。raise语句的组成是:raise+可选的要引发的类或者类的一个实例。

如果传递的是一个类,其实python会调用不带构造函数参数的类,以创建被引发的一个实例;这个格式等同于在类后面添加圆括号。本质上仍然是传递了一个对象。

我们看一个例子:对于之前我们经常看到的IndexError,下面两种形式是对等的,

raise IndexError
raise IndexError()

都会引发指定异常类的一个实例,其中第一种形式隐式的创建实例。

当使用下列的语法形式的时候

try:
    pass
except IndexError as e:
    print(e.args)

实质是把捕捉到的异常对象赋予了e这个变量名,这样可以方便的访问异常实例的数据以及异常类中的方法。

Python爱好者社区历史文章大合集

Python爱好者社区历史文章列表(每周append更新一次)

福利:文末扫码立刻关注公众号,“Python爱好者社区”,开始学习Python课程:

关注后在公众号内回复“课程”即可获取:

小编的Python入门免费视频课程!!!

【最新免费微课】小编的Python快速上手matplotlib可视化库!!!

崔老师爬虫实战案例免费学习视频。

陈老师数据分析报告制作免费学习视频。

玩转大数据分析!Spark2.X+Python 精华实战课程免费学习视频。


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存