软件程序在运行过程中,非常可能遇到刚刚提到的这些问题,我们称之为异常,英文是:Exception,意思是例外。遇到这些例外情况,或者叫异常,我们怎么让写的程序做出合理的处理,安全的退出,而不至于程序崩溃呢?我们本章就要讲解这些问题。工作中,程序遇到的情况不可能完美。比如:程序要打开某个文件,这个文件可能不存在或者文件格式不对;程序在运行着,但是内存或硬盘可能满了等等。
伪代码说明异常机制如果我们要拷贝一个文件,在没有异常机制的情况下,我们需要考虑各种异常情况,伪代码如下:
这种方式,有两个坏处:1逻辑代码和错误处理代码放一起!2程序员本身需要考虑的例外情况较复杂,对程序员本身要求较高!如上情况,如果是用Python的异常机制来处理,对比如下:
python中,引进了很多用来描述和处理异常的类,称为异常类。异常类定义中包含了该类异常的信息和对异常进行处理的方法。下面较为完整的展示了python中内建异常类的继承层次:
我们处理一下,遇到的第一个异常:
python中一切都是对象,异常也采用对象的方式来处理。处理过程:抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给解释器。12捕获异常:解释器得到该异常后,寻找相应的代码来处理该异常
异常的解决思路
解决异常问题的态度:
1. 学习完异常相关,只是开始对异常有些认识,不意味着你会调试任何异常;调试异常,需要大量的经验作为基础。因此,大家不要在此停留,继续往后学习。碰到每个异常,都要花心思去解决而不要动不动张口问人。通过自己的努力无法解决,再去找工具帮助解决。
2. 解决每一个遇到的异常,建议大家遵循如下三点:不慌张,细看信息,定位错误。看清楚报的错误信息,并定位发生错误的地方。
百度并查看十个相关帖子。将异常类信息进行百度,至少查看十个以上的相关帖子。
正常情况,自己遵循如上步骤解决30个以上的错误,就能积累初步的调试经验,以后遇到的大部分错误都能独立完成。
异常解决的关键:定位当发生异常时,解释器会报相关的错误信息,并会在控制台打印出相关错误信息。我们只需按照从上到下的顺序即可追溯(Trackback)错误发生的过程,最终定位引起错误的那一行代码。
【示例】追溯异常发生的过程
def a():
print("run in a() start! ")
num = 1/0
print("run in a() end! ")
def b():
print("run in b() start!")
a()
print("run in b() end! ")
def c():
print("run in c() start!")
b()
print("run in c() end! ")
print("step1")
c()
print("step2")
控制台打印结果:
try和except结构:
1.try块包含着可能引发异常的代码,except块则用来捕捉和处理发生的异常。
2.执行的时候,如果try块中没有引发异常,则跳过ecept块继续执行后续代码;执行的时候,如果try块中发生了异常,则跳过try块中的后续代码,跳到相应的except块中处理异常;异常处理完后,继续执行后续代码。
【示例】遇到异常的执行顺序
# 测试简单的0不能做除数异常
try:
print("step1")
a = 3/0
print("step2")
except BaseException as e:
print("step3")
print(e)
print("step4")
除数为0,遇到异常输出结果:
上面的结构可以捕获所有的异常,工作中也很常见。但是,从经典理论考虑,一般建议尽量捕获可能出现的多个异常(按照先子类后父类的顺序),并且针对性的写出异常处理代码。为了避免遗漏可能出现的异常,可以在最后增加BaseException。结构如下:
try:
被监控的、可能引发异常的语句块
except Exception1:
处理Exception1的语句块
except Exception2:
处理Exception2的语句块
[...]
except BaseException:
处理可能遗漏的异常的语句块
try...except...else结构try...except...else结构增加了else块。如果try块中没有抛出异常,则执行else块。如果try块中抛出异常,则执行except块,不执行else块。
try:
a = input("请输入被除数:")
b = input("请输入除数:")
c = float(a)/float(b)
except BaseException as e:
print(e)
else:
print("除的结果是:",c)
【示例】try...except...finally结构简单测试
return语句和异常处理问题由于return有两种作用:结束方法运行、返回值。我们一般不把return放到异常处理结构中,而是放到方法最后。
【示例】return和异常结构的正确处理方式
def test01():
print("step1")
try:
x = 3/0
# return "a"
except:
print("step2")
print("异常:0不能做除数")
#return "b"
finally:
print("step4")
#return "d"
print("step5")
return "e" #一般不要将return语句放到try、except、else、finally块中议放到方法最后。
print(test01())
常见异常