10.1.异常处理

当我们的代码的某个地方发送能被解释器感知的错误(比如除以0的语句 a=4/0),这时候继续执行下面的代码就没有意义了

解释器这时会,中断当前代码的执行,并抛出一个异常对象,并在函数的调用栈从里到外,一层层的寻找出力该异常的代码,如果能找到就执行对应

的代码,如果不能则会一直找到最外层的函数结束本次执行

 

异常的抛出和处理机制给了程序员通过异常处理代码的能力

10.1.1.异常的产生

大家在学习课程的过程中,肯定遇到过执行代码出现问题的时候,通常你们会注意带一个Traceback这样的东西打印在屏幕上,像下面这样

第十章、异常的捕获和处理_LeetCode

这里,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