异常捕获与处理


异常捕获和处理

一、基础知识

1、什么是异常

当我们写程序难免遇到报错,专业的称呼叫做异常,行业俗语叫做bug,由于异常情况出现会导致代码停止运行,所以在编写过程中要尽可能避免。

2、异常分类

语法错误

这一类错误很好理解,相当于你不会写,比如用if或for的时候不知道他们怎么写,这种情况比较夸张了,好好学过的人都不会犯这种错误,一般来说这种错误发现了就是要准备跑路了。

逻辑错误

这种情况在编写的时候是允许出现的,通常来说都是代码结构完整,但是在调用的时候出了各种错误如:顺序错了或是变量用错了导致的异常。

3、异常的结构

我们可以分成三部分看:

错误位置

报错的位置是占最大部分的,我们从这里知道什么位置运行代码出错了,通常来说在错误位置很多的时候只用看最下面那个。

错误类型

最下面一行左边的几个单词是标志你的错误类型的,通常也不用管,起到提示作用

错误详情

这里比较关键,错误详情会把你错误的地方进行一个具体的解释,好让你找到错误并改正

二、异常常见类型

当我们在编写python代码的时候会出现各种原因导致的异常,这里我们可以举一些常见的例子:

1、AssertionError

当 assert 语句失败时将被引发。用户利用断言语句检测异常时,如果断言语句检测的表达式为假,则会引发这种异常。

2、KeyError

KeyError是关键字错误,当在现有键集合中找不到指定的映射(字典)键时就会引发错误。这个异常主要发生在字典中,比如当用户试图访问一个字典中不存在的键时会被引发。

3、NameError

NameError是当某个局部或全局名称未找到时将被引发,也就是指变量名称发生错误,比如用户试图调用一个还未被赋值或初始化的变量时会被触发。

4、ValueError

当操作或函数接收到具有正确类型但值不适合的参数,也就是值错误,比如想获取一个列表中某个不存在值的索引。

5、SystemError

当解释器发现内部错误,但情况看起来尚未严重到要放弃所有希望时将被引发。 关联的值是一个指明发生了什么问题的字符串(表示为低层级的符号)。

6、SyntaxError

SyntaxError主要是因为当解析器遇到语法错误,比如少个冒号、多个引号之类的,编程时稍微疏忽大意一下就会出错,应该是最常见的一种异常错误了。

7、TypeError

TypeError是类型错误,当一个操作或函数被应用于类型不适当的对象时将被引发。比如在要求 int 时却传入了 list就会导致错误。

8、IndexError

当序列抽取超出范围时将被引发,也就是索引超出范围,比如最常见下标索引超出了序列边界,比如当某个序列m只有三个元素,却试图访问m[4]。

9、StopIteration

StopIteration为迭代器错误,由内置函数 next() 和 iterator 的 __next__() 方法所引发,用来表示该迭代器不能产生下一项。当访问至迭代器最后一个值时仍然继续访问,就会引发这种异常。

10、AttributeError

AttributeError是属性错误,当属性引用或赋值失败时就会出现。比如列表有index方法,而字典却没有,所以对一个字典对象调用该方法就会引发该异常。

11、AttributeError    

访问的对象属性不存在

12、ImportError    

无法导入模块或者对象,主要是路径有误或名称错误    

13、IndentationError 

代码没有正确对齐,主要是缩进错误

14、IOError        

输入/输出异常,主要是无法打开文件

15、OverflowError    

数值运算超出最大限制

16、TabError    

Tab和空格混用

17、ZeroDivisionError    

除法运算中除数0 或者 取模运算中模数为0

三、异常处理语法结构

在python中我们有专门的语法结构来应对一些将要出错的代码:

语法结构:

try:
	待监测的代码(可能会出错的代码)
except 错误类型 as e:
	针对上述错误类型制定的方案

功能讲解:

1、我们也可以根据这里面单词的意思大概看出来这个语法结构的作用,第一个单词在这里可以看成是尝试的意思,相应的我们把需要监测的代码放里面运行,第二个单词是期望的意思,就是说如果代码出现的错误是我们所期望的这个,那么就用下面的子代码进行处理,如果期望类型错了就会报错,对了就不会报错。

2、except后面的as e可以不写,写了的话会返回系统提示的报错信息。

3、当我们使用try监测代码的时候只能监测一个错误,当代码检测到第一个错误的时候就会输出提示信息然后停止代码的运行,后面的错误就不会被检测到。

4、这里我们也发现了,一个except只能应对一种错误类型,如果错误类型很多的话我们有两种选择,一种是写很多个except把错误类型写全,第二种选择是在错误类型处写上Exception/BaseException,就是后面要说的万能异常。

try:
	待监测的代码(可能会出错的代码)
except 错误类型1 as e:  # e就是系统提示的错误信息
	针对上述错误类型1制定的方案
except 错误类型2 as e:  # e就是系统提示的错误信息
	针对上述错误类型2制定的方案
except 错误类型3 as e:  # e就是系统提示的错误信息
	针对上述错误类型3制定的方案
 	 ...

万能异常

对应的异常类型是:Exception/BaseException

两个异常类型作用一样,都包含所有的错误类型,但是BaseException是Exception的父代码。

try:
	待监测的代码(可能会出错的代码)
except Exception as e:  # e就是系统提示的错误信息
	针对各种常见的错误类型全部统一处理

try语法结构结合else和finally

try结构结合else和finall功能很简单:

1、else后面跟的子代码是在try的子代码正常运行的时候才会执行的

2、finally是不管try的子代码运行是否正确都会运行的代码

try:
	待监测的代码(可能会出错的代码)
except Exception as e:  # e就是系统提示的错误信息
	针对各种常见的错误类型全部统一处理
else:
	try的子代码正常运行结束没有任何的报错后 再执行else子代码
finally:
	无论try的子代码是否报错 最后都要执行finally子代码

注意事项

1、虽然异常处理可以防止代码报错停止运行,但是这并不意味着我们可以多用异常处理减少异常。

2、异常处理应该尽量少用,当出现无法控制的情况报错才考虑使用,如手机软件在无法访问网络的时候使用异常处理进行提示现在没网不能运行。

3、try语法结构下监测的代码应该尽量少一些。

四、异常处理补充

1、断言

断言就是对一段代码进行判断,如果判断结果正确就继续运行,如果判断错误了就抛出AssertionError异常,直接中断代码的运行

name = 'jason'
# assert isinstance(name, int)
assert isinstance(name, str)
print('哈哈哈 我就说吧 肯定是字符串')
name.strip()

这里我们用isinstance判断数据的类型,如果把name绑定的字符串换成列表就会中断代码的运行抛出AssertionError异常。

2、主动抛出异常

跟上面的断言原理相似,当我运行代码检测到指定的数据值或条件的时候就直接抛出异常中断代码的运行。主动抛出异常需要用到raise这个方法,或是断言中的assert方法。

raise 异常类型名称(‘异常描述')

name = 'jason'
if name == 'jason':
	raise Exception('老子不干了')
else:
	print('正常走')

当name绑定的值是字符串jason的时候就抛出异常中断代码运行。

五、异常处理实战应用

课堂练习:

使用while循环+异常处理+迭代器对象 完成for循环迭代取值的功能

l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
die_qi = l1.__iter__()
while True:
    try:
        res = die_qi.__next__()
        print(res)
    except Exception as e:
        print('数据取完了')
        break

这里的Exception错误类型范围太广了,我们换成StopIteration异常类型也是一样的作用。


posted @ 2022-10-16 19:32  致丶幻  阅读(58)  评论(0编辑  收藏  举报