一文看懂Python异常小知识

共 2091字,需浏览 5分钟

 ·

2020-05-06 23:20

咪哥杂谈


d25b0687942625e723145d6b95f5dd95.webp

本篇阅读时间约为 8 分钟。文字约1600+


1

前言


今天这篇想介绍下 Python 的一个基础知识点。
在早期的 Python 小课堂中,好像并没有写到关于 Python 异常的知识点,那本期就来介绍下 Python 异常相关的知识点。


2

什么是异常?


开始讲解之前,先来了解下程序中的概念。


1. 什么是异常?


异常两个字,用大众化的理解就是,当做一件你规划好的事时,中途出现了打断你预期计划的因素,此时这个因素称之为异常。
简单举个例子。

西天取经路线:


bd8722d2fbd4980c6b94a5e1de6ec5b9.webp


图片来源:http://www.sdmzh.com.cn/map/index.html
唐僧西天取经,从长安开始,到摩揭陀国结束。一路规划行程,每个红旗就是途径的地点。

这行进路线就像是一套完整的流程,但总有意外的妖怪冒出来打断唐僧前进的路,只有当消灭妖怪之后,才能继续前行。
对应到程序中,代码开始运行的地方则是唐僧的出发点,结束的地方则是唐僧的取经地点。妖怪一旦出来打断,你就无法前行。异常一旦出现,你的代码就无法继续正常往下运行了。
用代码来看下,我们常见的异常长什么样子:


2dfa1240b6a34c8c122810acb62834c2.webp


1/0,0不能被整除。

通过这个小例子,用程序的概念再来重塑一遍异常的定义。有时 Python 程序的语法是正确的(比如 Pycharm 没有提示你红线),但在程序运行期间,导致程序中断的错误被称为异常。
2. 与 异常 容易混淆的一个概念是 错误 。
什么是错误?例如语法错误:


9d2dff708857b97f8f39b59a4244cba5.webp


在 Python3 中,print 函数新加了小括号才能进行打印,否则就是语法错误
这里留个小问题,你觉得异常和错误有什么区别?看 Python 提示都是XxError(SyntaxError、ZeroDivisionError),为什么不一样?
下面会说下这个问题的答案。


3

异常处理


程序运行期间发生异常最大的影响就是会打断程序的正常运行。
那么,有没有办法处理它呢?(孙悟空最厉害的不就是"捉妖怪"吗!)
Python 为我们提供了一个可以捕获异常的语法,即 try-except


1. 整除0异常捕获


a08052a02b7367cb7245c26f9394fd7b.webp


可以看到,异常被 except 代码块捕获了,并打印了发生异常。
如果你想解决问题,想看具体哪行代码发生了异常,这样的打印显然是不行的,你可以用下面这种方式:

5271ef5b594d31166cb63834b18f309f.webp


2. raise 主动抛出异常


异常,也可以手动制造,在处理一些特殊的业务场景下,当到达了临界需求,则需要手动抛出异常,将程序终止返回。如下面:


2ba270b961a67315591ec681496c6016.webp


3. finally 理捕获异常


finally 语句,无论是否发生异常都将执行 finally 中的代码。


八戒和唐僧的对话:


a50e026c39e4073e47f5295d32690802.webp


利用 finally :


27556ed57f884e26e8080d47ebb20713.webp


没有异常的场景下:

a1c60f275b52d80c861d03d5c5a6887d.webp



一般 finally 的使用场景,都是做一些清理资源的工作。比如用 open 打开文件,最终 finally 中释放资源引用。忘记的同学回顾:

python小课堂39 - 用 with 优雅的读写文件


4. 异常和错误的不同之处


回答下上面抛出的问题:
  • 错误是捕获不到的
  • 异常可以捕获到,并可以进行处理


以语法错误为例,except中的代码没有打印:


e07d6a1158ed331941deda0dc565a61e.webp


4

自定义异常


Python 提供了一个 BaseException 的类,但凡继承它的子类,都属于异常类,这样对于写代码的人来说,异常类是支持自行定义的。


在 Python 中,有个魔法函数 __mro__,通过它,可以看到类的继承关系。


来分别看下常见的三种异常:


  • ZeroDivisionError

  • NameError

  • TypeError


ee11c17a90ecc4856934ba7eae2d3b4d.webp


但平时自定义异常,继承 Exception 即可。


自定义一个说话的异常:


eaf644fa9ba93e3362e2821e8663df35.webp


当调用异常时,触发了 __init__ 方法传参,打印对象引用 e 时,触发了 __str__ 方法。
自定义类的场景,多数要看业务逻辑,举个例子。

比如在 web 交互中,你作为服务端提供 api 服务,不同的业务都会发生不同的异常,有的异常需要返回给调用端是正常的 200 健康 http 状态码,有的异常则需要处理成不健康的状态码,比如 400 或者 500 之类的。

不同异常,在 Controller 层(视图层)拦截到,根据业务进行不同处理。


5

异常的使用场景


常见的两种场景:


  • 预料不到的情况,需要异常捕获,比如爬虫解析html节点,没解析到,空指针异常。


  • 业务边界的情况,比如web交互,系统之间相互调用,服务端内部系统异常,需要封装异常做些业务处理,再讲相关信息回传给调用端。(刚才举例的自定义异常)


6

总结


写的又有点多了。如果你能看到这里,说明异常的基本用法应该了解了。


简单的再来回顾下学到了什么:


  • 异常的基本定义

  • 捕获异常的用法 try-except

  • raise 主动抛出异常

  • finally 关键字的使用

  • 异常和错误的区别

  • 如何自定义异常?


那,本期的内容到此结束,如果你有什么疑问或者想对我说的,欢迎评论区留言探讨。


PS:公众号新出了一个专辑功能,我把之前Python小课堂相关文章都整理进去了,但是预览文章的时候看不到按钮在哪里,有可能发出去,文章最上面的布局会乱掉,试下新功能看看吧~




▼往期精彩回顾▼推荐个网站!
这样的搜索姿势,真是爽爆了!!~




浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报