10.1.异常处理
当我们的代码的某个地方发送能被解释器感知的错误(比如除以0的语句 a=4/0),这时候继续执行下面的代码就没有意义了
解释器这时会,中断当前代码的执行,并抛出一个异常对象,并在函数的调用栈从里到外,一层层的寻找出力该异常的代码,如果能找到就执行对应
的代码,如果不能则会一直找到最外层的函数结束本次执行
异常的抛出和处理机制给了程序员通过异常处理代码的能力
10.1.1.异常的产生
大家在学习课程的过程中,肯定遇到过执行代码出现问题的时候,通常你们会注意带一个Traceback这样的东西打印在屏幕上,像下面这样
这里,Traceback就是告诉我们程序执行有异常抛出了,异常就是最下面的这个NameError。它是异常对象的一种
上面的示例代码中没有什么函数调用,所以看不出来异常排出的轨迹,我们来看下面这个例子
def foo3(): print("in f3") b = 4/0 def foo2(): print('in f2') foo3() def foo1(): print('in f1') foo2() foo1()
这里函数foo1会调用函数foo2,函数foo2会调用函数foo3。但是foo3里面有个明显的错误-分母为0
执行上面的代码,我们得到如下输入结果
D:\tools\Python37-32\python.exe E:/samples/test/tr.py in f1 in f2 in f3 Traceback (most recent call last): File "E:/samples/test/tr.py", line 14, in <module> foo1() File "E:/samples/test/tr.py", line 11, in foo1 foo2() File "E:/samples/test/tr.py", line 7, in foo2 foo3() File "E:/samples/test/tr.py", line 3, in foo3 b = 4/0 ZeroDivisionError: division by zero
这里解释器把整个异常抛出的路径给显示出来了。我们从上到下看,就是函数调用栈,直到出现错误的地方
10.1.2.异常的捕获和处理
异常被抛出后,如果没有捕获处理,那么会导致当前程序的异常退出。
python通过try...except...finally...这样的方法来捕获和处理异常
看下面的代码
try: b=4/0 except ZeroDivisionError print('handle ZeroDivisionError')
执行结果:
handle ZeroDivisonError
没有tracebark打印在屏幕上高速我们出错的信息了。因为除以0的异常被try...except捕获了。并执行了except里面的代码。而except后面跟着ZeroDivisionError是用
来指明它这段代码是要专门捕获ZeroDivisionError异常后执行
** 捕获多种异常
我们可以连接有好几个except代码段来分别捕获不同类型的异常,如下
try: ohmy b = 4/0 except ZeroDivisionError: print('handle ZeroDivisionError') except NameError: print('handle NameError')
执行结果为:
handle NameError
由于执行到ohmy这句话就产生了异常,并且该异属于NameError类型,所以他被except NameErrot所捕获,执行了相应的代码。而except ZeroDivisionErrot不是对应的该异常类型
所以它对应的代码不会执行
如果没有异常产生,则except对应的语句块里面的代码不会被执行
** 得到异常对象
有的时候,我们在捕获异常的时候得到更具体的异常信息,会这样
try: ohmy except NameError as e: print('hanle NameError:' e)
输出结果如下:
handle NameError:name 'ohmy' is not defined
上面的e就是异常对象本身,我们可以打印出异常对象里面存储的具体错误信息
** 捕获所以异常
有的时候,我们并不知道会抛出什么样的异常,但是我们并不希望有未知异常抛出的时候,程序被异常中止,这时候蜗牛可以捕获所以类型的异常,如下:
try: ohmy except Exception as e: print('handle unkown exeption:' e)
执行结果如下:
handle unkown exeption:name 'ohmy is not defined'
也可以简单写出这样
try: ohmy except: print('handle unkown exeption')
如果我们想看看异常抛出的详细调用栈的信息可以这样写
import traceback try: ohmy except: print('handle unkown exeption\n' + traceback.format_exc())
** finally语句
有的时候,不管 是否有异常,我们都有执行一段代码,可以用关键字finally
try: ohmy b = 4/0 except ZeroDivisionError: print('handle ZeroDivisionError') except NameError: print('handle NameError') except: print('handle unkown exeption') finally: print('in finally')
执行结果如下
D:\tools\Python37-32\python.exe E:/samples/test/tr.py handle NameError in finally