Python基础(九)--异常

                                      Python基础(九)--异常

1 异常相关概念

1.1 什么是异常

异常是程序运行过程中产生的一种事件,该事件会打乱程序的正常流程。可以说,异常就是一种意外,指程序没有按照正常或期望的方式执行。

当异常产生时,会创建一个相关异常类的对象,该对象含有异常的相关信息。异常产生时,会在异常的上下文中寻找异常处理程序,如果没有异常处理程序,则异常产生之后的语句将不会得到执行。该异常会向上传播。传播的方式为:

①如果异常是在函数中产生的,则传播给函数的调用者

②如果异常是在模块顶级位置产生的,则传播给导入该模块的另一个模块

如果当前模块作为脚本运行,则异常会传播给解释器,如果到了解释器,异常还未解决,则当前线程会终止执行。离异常产生越近的信息,会在越下面显示,因此分析异常时,应该从下往上看。

def A():B()
def B():C()
def C():a = 6 / 0
A()

1.2 常见异常类型

异常命名惯例,以Error结尾。

异常类型描述
BaseExceptionPython中所有异常的根类
ExceptionBaseException的子类,用户异常的根类
ZeroDivisionError当除数为0时,产生的异常
AssertionError断言的异常,当断言条件不满足时产生
ModuleNotFoundError当使用import导入的模块不存在时产生的异常
IndexError索引异常,当索引越界时产生
KeyError键访问异常,当键不存在时会产生
NameError名称异常,当访问名称不存在时产生
RecursionError递归异常,当函数调用层次达到最大层次限制时产生
StopIteration迭代终止异常,当迭代器已经没有元素是产生
SyntaxError语法错误异常,编写的代码不符合语法规定时产生
ValueError值异常,当对值处理错误是产生

2 捕获异常

2.1 try...except

在Python中,可以使用try-except的语法来捕获异常,我们可以将其称为异常处理程序。格式如下:

try:可能产生异常的程序except 异常类型1:恢复措施except 异常类型2:恢复措施……except 异常类型n:恢复措施

其中,try用来执行可能会产生异常的程序,而except用来捕获try中产生的异常,用来执行一些恢复或补救操作,或者给出错误的提示信息等。这分为三种情况:

①try语句块没有产生异常。

此时try语句块全部执行完毕,不会执行任何except分支(因为没有异常),然后继续执行try-except之后的语句。

②try语句块中产生异常,except捕获了该异常。

会创建相关异常类型的对象,try异常之后的语句不会得到执行(不论except能否捕获该异常)。然后对该异常对象与各个exception分支不会的异常类型进行匹配。匹配的原则为:isinstance(异常对象,except捕获的异常类型),如果匹配成功,则执行对应的except分支,匹配顺序从上到下。如果能够匹配成功,表示成功捕获异常,try-except之后的语句可以正常执行。

③try语句块中产生异常,但是except没有捕获该异常。

如果try中产生异常,但是except没有捕获该异常,则该异常继续存在,try-except之后的语句不会得到执行。该异常向上传播

捕获异常对象:可以使用except捕获异常,同时,我们也能够使用as语法获取try中产生的异常对象。语法格式为:

try:可能产生异常的代码
except 异常类型 as 变量:处理异常代码

当异常匹配成功时,我们就会将try中产生的异常对象赋值给as变量名,然后,我们就可以在except中使用变量名来访问异常对象了。

try:print(5 / 0)
except ZeroDivisionError as e:# 通过异常对象的args属性获取异常对象构造器的参数。print(e.args)

异常对象的args属性返回一个元组类型,其中存放异常对象创建时,传递给构造器中的参数值。

 

2.2 捕获多个一次

因为在try语句块中,可能产生不止一种异常,故我们会使用多个except分支来捕获这些可能产生的异常。如果多个异常类之间没有继承关系时,except分支的顺序不是十分重要,但是,当异常类之间存在异常关系时,就一定要将子类放在前面,父类放在后面。因为子类异常对象也是父类异常类的实例,如果将父类分支放在子类分支之前,则就算try中产生子类异常,也会先由父类分支率先捕获,子类分支永远都没有机会执行,这就失去了意义。所以,在捕获异常时,except分支应该按照从特殊性(子类)到一般性(父类)的方式排序。

except还有一种语法,就是不指定异常类型,此时表示捕获所有异常类型。因为捕获所有的异常类型是最广泛的(最具有一般性),所以,如果使用这种方式,则必须将该except置于最后(作为最后一条except分支)。例如:

try:可能产生异常的代码
except:				# 没有指定异常类型,会捕获所有的异常。pass

 

同时捕获多个异常:当try中产生了两种(或更多)的异常,而多种异常的处理方式又完全相同时,我们使用多条except分支,会造成代码的重复。此时,我们可以使用一条except分支,同时捕获多个异常来代替。

try:# 操作
except (IndexError, KeyError):print("提供值不合法,获取失败!")

这样,无论try中产生IndexError还是KeyError,except分支都可以进行捕获。也许大家会有这样的想法,这种捕获多个异常有什么用呢,使用不指定异常类型的except岂不是更好,能捕获所有异常,可谓“万事通用”。

try:# 操作except:print("提供值不合法,获取失败!")

但是,如果这样做,就很可能会捕获预期之外的异常,从而掩埋真正的问题,令错误不易排查。因此,如果能够捕获更加具体明确的异常类型,我们最好不要使用更加通用一般的异常类型代替。

2.3 else

try-except还可以跟随可选的else语句。语法为:

try:……
except 异常类型:……
else:……

当try中没有产生异常时,就会执行else分支,否则,不执行else分支。似乎感觉,else分支并没有什么作用,完全可以将else分支放在try语句块的后面啊,因为如果产生异常,try中异常之后的语句也不会执行。如果从程序(计算机)的角度讲,确实可以这样进行修改,然而,如果从程序员的角度讲,else还是具有一定的意义的。因为,其可以将“可能产生异常的代码”与“不产生异常后执行的代码”进行有效的分离,从而让程序更加清晰,具有可读性。

else语句的作用:try中的语句应该是可能产生异常的语句,对于不会产生异常的语句,我们就不适合放在try中。else就可以将try中不产生异常的语句从try中分离,令程序结构变得更加清晰。

2.4 finally

try-except还可以带上一个可选的finally。如果同时存在else,则finally必须处于else的后面,其实,except,else,与finally都是可选的。但是,except与finally二者不能同时缺失,即二者至少要存在一个。

finally会在try-except-else之后得到执行(如果存在except或else的话),且一定会得到执行。即无论try是否产生异常,也无论except是否捕获try中产生的异常,finally终将会得到执行。

考虑到finally总是可以执行的特征,我们往往会在finally中执行一些清理的工作。例如,我们在try中申请了一些系统资源(文件读写,数据库连接等),就可以在finally中进行资源释放,从而不会造成资源泄露(资源申请,但没有释放)。如果将释放语句写在try中,则一旦在释放之前产生异常,则资源释放语句就不会得到执行。

# 在try和finally中同时又return时,finally中的return会镇压掉try中的
def fun():try:return 1finally:return 2
print(fun())
# 当try语句体中尝试返回一个变量时,如果在finally中去修改该变量的值,
# 不会影响到返回值的结果(返回的还是修改之前的值)
def fun2():a = 1try:return afinally:a = 2
print(fun2())
# 验证finally是否总会执行
# 1在循环中,通过break尝试跳过finally语句块
for i in range(10):try:breakfinally:print("finally总会执行")
# 2、在方法中,执行return尝试跳过finally语句块。
def f():try:returnfinally:print("finally总会执行")
f()
# 3、调用sys模块的exit方法,尝试跳过finally语句块
import sys
try:sys.exit()
finally:print("finally总会执行")

3 抛出异常

在不符合要求时,可以主动产生一个异常,这样就能够给客户端一个有效的提醒。我们可以创建一个异常对象,使用raise抛出,语法为:

raise 异常类或异常对象

例如:raise Exception("产生异常")

raise Exception

raise后面跟随异常类,则相当于是调用其无参的构造器,因此,后者相当于:

raise Exception()

raise后面必须是一个有效的异常类(BaseException类型或其子类型)或对应异常类的对象,如果是其他类型,将会产生错误。

4 自定义异常

自定义异常通常继承Exception类型(或其子类型),按照惯例,异常类以Error结尾。

为什么需要自定义:①Python提供的异常类型不能满足所有的用户,所有场景的需要。②自定义异常可以与Python系统提供的异常类型分开,有利于定位并解决问题

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473698.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬虫工具:虚拟机Selenium和PhantomJS,ChromeDriver 镜像安装教程

虚拟机Ubuntu 16.04中安装: 1.安装Selenium命令:pip install Selenium 2.安装PhantomJS命令:sudo apt install PhantomJS 3.找到Ubuntu中谷歌所对应的的版本号: 看到网上基本没有最新的chromedriver与chrome的对应关系表&#xff…

Python基础(十)--文件相关

目录 Python基础(十)--文件相关 1 读写文件 1.1 获取文件对象 1.2 文件读取 1.3 文件写入 1.4 文件定位 2 文件与路径的操作 2.1 os模块 2.2 os.path模块 2.3 shutil模块 2.4 glob模块 3 序列化 3.1 csv 3.2 json 3.3 pickle 4 上下文管理…

memcache 原理 监测 查看状态 stats 结构

Mencache内存存储方式:slab/LRU,采用预先申请固定大小的内存页(slab/page),然后再把内存分成多个块(chunk) 先放一张从网上找到的memcache内存结构图,觉得非常的赞: 再来一张memcach…

爬虫——多线程糗事百科案例

Queue(队列对象) Queue是python中的标准库,可以直接import Queue引用;队列是线程间最常用的交换数据的形式 python下多线程的思考 对于资源,加锁是个重要的环节。因为python原生的list,dict等,都是not thread safe的…

LeetCode 1625. 执行操作后字典序最小的字符串(BFS)

文章目录1. 题目2. 解题1. 题目 给你一个字符串 s 以及两个整数 a 和 b 。其中,字符串 s 的长度为偶数,且仅由数字 0 到 9 组成。 你可以在 s 上按任意顺序多次执行下面两个操作之一: 累加:将 a 加到 s 中所有下标为奇数的元素…

C++ 0x 使用可变参数模板类 实现 C# 的委托机制

1 #ifndef _ZTC_DELEGATE_H_2 #define _ZTC_DELEGATE_H_3 4 #include <vector>5 #include <functional>6 7 ///8 // C 使用 可变参数模板类, 来实现9 // C#中的 委托 10 // Anchor: ztc 11 // Date : 2014-01-10 12 /// 13 14 template<typename R, typename …

爬虫技巧:在pycharm 下 调试 scrapy项目

&#xff08;1&#xff09; 用pycharm导入scrapy项目 &#xff08;2&#xff09;选择自己编写的scrapy&#xff0c;run一下 &#xff08;3&#xff09;点击菜单栏的run &#xff0c;选择Edit Configurations。 &#xff08;4&#xff09;选择运行的spider文件 &#xff08;5&am…

LeetCode 1626. 无矛盾的最佳球队(最大上升子序DP)

文章目录1. 题目2. 解题1. 题目 假设你是球队的经理。对于即将到来的锦标赛&#xff0c;你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数 总和 。 然而&#xff0c;球队中的矛盾会限制球员的发挥&#xff0c;所以必须选出一支 没有矛盾 的球队。 如果一名…

爬虫最基本的工作流程:内涵社区网站为例

网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟客户端发送网络请求&#xff0c;接收请求响应&#xff0c;一种按照一定的规则&#xff0c;自动地抓取互联网信息的程序。 只要是浏览器能做的事情&#xff0c;原则上&#xff0c;爬虫都能够做…

LeetCode 网易-2. 古老的游戏机

文章目录1. 题目2. 解题1. 题目 小易有一个古老的游戏机&#xff0c;上面有着经典的游戏俄罗斯方块。因为它比较古老&#xff0c;所以规则和一般的俄罗斯方块不同。 首先&#xff0c;荧幕上一共有 n 列&#xff0c;每次都会有一个 1 x 1 的方块随机落下&#xff0c;在同一列中…

RDD(弹性分布式数据集)

1、什么是RDD RDD&#xff08;分布式弹性数据集&#xff09;是对分布式计算的抽象&#xff0c;代表要处理的数据&#xff0c;一个数据集,RDD是只读分区的集合。数据被分片&#xff0c;分成若干个数据分片&#xff0c;存储到不同的节点中&#xff0c;可以被并行的操作&#xff…

爬虫Scrapy框架基本流程图入门:以东莞阳光网为例

一、Scrapy简单介绍 Scrapy是一个为了爬取网站数据&#xff0c;提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘&#xff0c;信息处理或存储历史数据等一系列的程序中。 所谓网络爬虫&#xff0c;就是一个在网上到处或定向抓取数据的程序&#xff0c;当然&#xff0…

Eclipse自动补全功能轻松设置 || 不需要修改编辑任何文件

本文介绍如何设置Eclipse代码自动补全功能。轻松实现输入任意字母均可出现代码补全提示框。Eclipse代码自动补全功能默认只包括 点"." &#xff0c;即只有输入”."后才出现自动补全的提示框。想要自动补全总是去按 “Alt / ”也很麻烦。 其实只需简单在Eclips…

RDD持久化、广播、累加器

1、持久化 RDD的持久化包括两个方面&#xff1a;①操作RDD的时候怎么保存结果&#xff0c;这个部分属于action算子的部分②在实现算法的时候要进行cache、persist&#xff0c;还有checkpoint进行持久化。 1.1 persist和cache Spark稍微复杂一点的算法里面都会有persit的身影…

LeetCode 网易-1. 分割环(前缀和 + 哈希)

文章目录1. 题目2. 解题1. 题目 小易有 n 个数字排成一个环&#xff0c;你能否将它们分成连续的两个部分(即在环上必须连续)&#xff0c;使得两部分的和相等&#xff1f; 输入描述&#xff1a; 第一行数据组数 T &#xff0c;对于每组数据 第一行数字 n &#xff0c;表示数字…

RDD的依赖与分区

1 宽依赖和窄依赖 RDD从具体的依赖的角度讲&#xff0c;有窄依赖和宽依赖2种情况。 窄依赖&#xff1a;指每个父RDD的一个Partition最多被子RDD的一个Partition所使用&#xff0c;例如map、filter等都会产生窄依赖&#xff1b; 宽依赖&#xff1a;指一个父RDD的Partition会被…

爬虫案列:京东商城长裤信息获取

1、创建Scrapy项目 使用全局命令startproject创建项目&#xff0c;创建新文件夹并且使用命令进入文件夹&#xff0c;创建一个名为jingdong的Scrapy项目。 [python] view plaincopy scrapy startproject jingdong 2.使用项目命令genspider创建Spider [python] view plaincopy …

ACwing 2. 01背包问题(DP)

文章目录1. 题目2. 解题1. 题目 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 …

Redis-Scrapy分布式爬虫:当当网图书为例

Scrapy-Redis分布式策略&#xff1a; Scrapy_redis在scrapy的基础上实现了更多&#xff0c;更强大的功能&#xff0c;具体体现在&#xff1a; reqeust去重&#xff0c;爬虫持久化&#xff0c;和轻松实现分布式 假设有四台电脑&#xff1a;Windows 10、Mac OS X、Ubuntu 16.04、…

Saprk排序

1、基础排序算子sortBy和sortByKey 在Spark中存在两种对RDD进行排序的函数&#xff0c;分别是 sortBy和sortByKey函数。sortBy是对标准的RDD进行排序&#xff0c;它是从Spark0.9.0之后才引入的。而sortByKey函数是对PairRDD进行排序&#xff0c;也就是有Key和Value的RDD。下面…