Day 9
导引问题
在实际工作中,我们遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求;你的程序要打开某个文件,这个文件可能不存在或者文件格式不对;你要读取数据库的数据,数据可能是空的;我们的程序再运行,但是内存或硬盘可能满了等等。
软件程序再运行过程中,非常可能遇到刚刚提到的这些问题,我们称之为异常,英文是:Exception,意思是例外。遇到这些例外情况,或者叫异常,我们怎么让写的程序做出合理的处理,而不至于程序崩溃呢?
如果我们要拷贝一个文件,在没有异常的情况下,我们需要考虑各种异常情况,伪代码如下:
【示例】伪代码使用if处理程序中可能出现的各种情况
#将d:/a.txt拷贝到e:盘
if 'd:/a.txt'这个文件存在:
if e盘的空间大于a.txt文件长度:
if 文件复制一半IO流断掉:
停止copy,输出:IO流出问题!
else:
copyFile('d:/a.txt','e:/a.txt')
else:
print('e盘空间不够存放a.txt!')
else:
print('a.txt不存在!')
这种方式有两个坏处:
- 逻辑代码和错误处理代码放在一起!
- 程序员本身需要考虑的例外情况较复杂,对程序员本身要求较高!
那么我们如何解决应对异常情况呢?Python的异常机制给我们提供了方便的处理方式。如上情况,如果是用python的异常机制来处理,示意代码如下(仅限示意,不能运行):
#将d:/a.txt拷贝到e:盘
try:
copyFile(‘d:/a.txt','e:/a.txt’)
except:
print(‘无法拷贝文件’)
异常机制本质
异常指程序运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。
所谓异常处理,就是指程序再出现问题时依然可以正确的执行剩余的程序,而不会因为异常而终止程序执行。
python中,引进了很多用来描述和处理异常的类,称为异常类。异常类定义中包含了该类异常的信息和对异常进行处理的方法。下面较为完整的展示了python中内建异常类的继承层次:
我们处理一下,遇到的第一个异常
#测试简单的0不能做除数异常
a = 3/0
结果:
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/MyDemo/day1/异常.py", line 1, in <module>
a=3/0
ZeroDivisionError: division by zero
Python中一切皆是对象,异常也采用对象的方式来处理。处理过程:
1.抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给解释器。
2.捕获异常:解释器得到该异常后,寻找相对应的代码来处理该异常
#Traceback追溯,追根溯源,most recent call last最后一次调用
def a():
num = 1/0
def b():
a()
def c():
b()
c()
解决异常问题的态度
学习完异常相关知识点,只是开始对异常有些认识,不意味着你会调试任何异常;调试异常,需要大量的经验作为基础。因此,大家不要在此停留,继续往后学习。碰到每个异常,都要花心思去解决而不要动不动张口问人,通过自己扥努力无法解决,再去找老师同学帮助解决。
解决每一个遇到的异常,建议大家遵徐如下三点:
- 不慌张,细看信息,定位错误,看清楚报的错误信息,并定位发生错误的地方
- 百度并查看十个相关帖子,将异常类信息进行百度,至少查看十个以上的相关帖子
- 以上两步仍然无法解决,找老师同学协助解决
正常情况,自己遵循如上步骤解决30个以上的错误,就能积累初步的调试经验,以后遇到大部分错误都能独立完成。
异常解决的关键:定位
当发生异常时,解释器会报相关的错误信息,并会在控制台打印出相关错误信息,我们只需按照从上到下的顺序即可追溯(Traceback)错误发生的过程
【示例】追溯异常发生的过程
结果:从上往下看,最终其实只有num = 1/0是错误的
Traceback (most recent call last):
File "C:/Users/Administrator/PycharmProjects/MyDemo/day1/异常.py", line 12, in <module>
c()
File "C:/Users/Administrator/PycharmProjects/MyDemo/day1/异常.py", line 10, in c
b()
File "C:/Users/Administrator/PycharmProjects/MyDemo/day1/异常.py", line 7, in b
a()
File "C:/Users/Administrator/PycharmProjects/MyDemo/day1/异常.py", line 4, in a
num = 1/0
ZeroDivisionError: division by zero
try...一个except结构
try...except是最常见的异常处理结构。结构如下:
try:
被监控的可能引发异常的语句块
except BaseException[as e]:
异常处理语句块
try块包含着可能引发异常的代码,except块则用来捕捉和处理发生的异常。执行的时候,如果try块中没有引发异常,则跳过except块继续执行后续代码;执行的时候,如果try块中发生了异常,则跳过try块中的后续代码,调到相应的except块中处理异常;异常处理完后,继续执行后续代码
·遇到异常的执行顺序
执行结果:
step1
step3
division by zero
step4
【示例】循环输入数字,如果输入的不是数字则处理异常,直到输入88,结束
#coding=utf-8
#示例,循环输入数字,如果不是数字则处理异常,直到输入88,则结束循环
while True:
try:
x = int(input('请输入一个数字'))
print('输入的数字:', x)
if x == 88:
print('退出程序')
break
except BaseException as e:
print(e)
print('异常,输入的不是一个数字')
print('循环数字输入程序结束')
结果: