Python第十章 异常
第十章 异常
10.1 异常概述
当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的“异常”, 也就是我们常说的BUG
bug命名的由来
早期计算机采用大量继电器工作,马克二型计算机就是这样的。
1945年9月9日,下午三点,马克二型计算机无法正常工作了,技术人员试了很多办法,最后定位到第70号继电器出错。负责人哈珀观察这个出错的继电器,发现一只飞蛾躺在中间,已经被继电器打死。她小心地用摄子将蛾子夹出来,用透明胶布帖到“事件记录本”中,并注明“第一个发现虫子的实例。”自此之后,引发软件失效的缺陷,便被称为Bug。
Python中的异常演示
# 以r方式打开一个不存在的文件
f = open("none.txt", "r")
# 错误:FileNotFoundError: [Errno 2] No such file or directory: 'none.txt'
# 0作除数
1 / 0
# 错误:ZeroDivisionError: division by zero
10.2 异常的捕获
世界上没有完美的程序,任何程序在运行的过程中,都有可能出现:异常,也就是出现bug导致程序无法完美运行下去。
我们要做的,不是力求程序完美运行。而是在力所能及的范围内,对可能出现的bug,进行提前准备、提前处理。
当我们的程序遇到了BUG, 那么接下来有两种情况:
- 整个程序因为一个BUG停止运行
- 对BUG进行提醒, 整个程序继续运行
显然在之前的学习中, 我们所有的程序遇到BUG就会出现①的这种情况, 也就是整个程序直接奔溃.
但是在真实工作中, 我们肯定不能因为一个小的BUG就让整个程序全部奔溃, 也就是我们希望的是达到② 的这种情况
那这里我们就需要使用到捕获异常
捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段。
10.2.1 异常except
有以下几种捕获形式:
- 基本语法(很少使用)
- 捕获指定异常
- 捕获指定的多种异常
- 捕获全部异常
【经验】如果要捕获全部异常的话,那么常常使用except Exception as的语法
下面逐一演示
1、基本语法
try:
可能发生错误的代码
except:
如果出现异常执行的代码
演示:尝试以r
模式打开文件,如果文件不存在,则以w
方式打开。
try:
f = open("none.txt", "r")
except:
f = open("none.txt", "w")
print("捕获到了异常,创建文件")
2、捕获指定异常
try:
可能发生错误的代码
except 指定的异常 as e:
如果出现异常执行的代码
演示:
# 此前未定义name
try:
print(name)
except NameError as e:
print("name变量名称未定义错误")
print(e) # name 'name' is not defined
但是只能捕获指定的异常,未指定的不会捕获
try:
1 / 0
except NameError as e:
print("捕获到了异常")
# 未捕获到,报错ZeroDivisionError: division by zero
【使用说明】① 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
② 一般try下方只放一行尝试执行的代码。
3、捕获指定的多个异常
try:
1 / 0
except (NameError, ZeroDivisionError) as e:
print("捕获到了异常")
捕获到了,使用()将多种异常围起来
4、捕获所有异常
有的时候可能不确定捕获的是什么异常,就捕获所有异常
try:
1 / 0
except Exception as e:
print(e) # division by zero
10.2.2 异常else
异常else:else表示的是如果没有异常要执行的代码。
try:
# 1 / 0
1 / 1
except Exception as e:
print(e)
else:
print("else, 没有捕获到异常") # else, 没有捕获到异常
10.2.3 异常finally
finally表示的是无论是否异常都要执行的代码,例如关闭文件。
try:
f = open("test.txt", "r")
except Exception as e:
print("文件打开失败,w形式创建文件")
f = open("test.txt", "w")
else:
print("文件存在,没有异常")
finally:
print("无论如何,关闭文件")
f.close()
10.3 异常的传递
异常是具有传递性的:
当函数func01中发生异常, 并且没有捕获处理这个异常的时候, 异常会传递到函数func02, 当func02也没有捕获处理这个异常的时候,main函数会捕获这个异常, 这就是异常的传递性.
当所有函数都没有捕获异常的时候, 程序就会报错
下面是演示
def func1():
print("func1 开始执行")
num = 1 / 0
print("func1 结束执行")
def func2():
print("func2 开始执行")
func1()
print("func2 结束执行")
def main():
func2()
main()
最下层是错误发送的位置,由下而上是异常由内而外传递
利用异常具有传递性的特点, 当我们想要保证程序不会因为异常崩溃的时候, 就可以在main函数中设置异常捕获, 由于无论在整个程序哪里发生异常, 最终都会传递到main函数中, 这样就可以确保所有的异常都会被捕获
def func1():
print("func1 开始执行")
num = 1 / 0
print("func1 结束执行")
def func2():
print("func2 开始执行")
func1()
print("func2 结束执行")
def main():
try:
func2()
except Exception as e:
print(e)
main() # division by zero