异常的捕获和处理
一、异常处理
当我们的代码的某个地方发送能被解释器感知的错误(比如除以0的语句 a=4/0),这时候继续执行下面的代码就没有意义了,解释器这时会,中断当前代码的执行,并抛出一个异常对象,并在函数的调用栈从里到外,一层层的寻找出力该异常的代码,如果能找到就执行对应的代码,如果不能则会一直找到最外层的函数结束本次执行,异常的抛出和处理机制给了程序员通过异常处理代码的能力。
二、异常的产生
大家在学习课程的过程中,肯定遇到过执行代码出现问题的时候,通常你们会注意带一个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
这里解释器把整个异常抛出的路径给显示出来了。我们从上到下看,就是函数调用栈,直到出现错误的地方
三、异常的捕获和处理
3.1.异常的捕获处理
异常被抛出后,如果没有捕获处理,那么会导致当前程序的异常退出。而python通过try...except...finally...这样的方法来捕获和处理异常,看下面的代码
try: b=4/0 except ZeroDivisionError print('handle ZeroDivisionError')
执行结果:
handle ZeroDivisonError
没有tracebark打印在屏幕上高速我们出错的信息了。因为除以0的异常被try...except捕获了。并执行了except里面的代码。而except后面跟着ZeroDivisionError是用
来指明它这段代码是要专门捕获ZeroDivisionError异常后执行
3.2.捕获多种异常
我们可以连接有好几个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对应的语句块里面的代码不会被执行
3.3.获取异常对象
有的时候,我们在捕获异常的时候得到更具体的异常信息,会这样
try: ohmy except NameError as e: print('hanle NameError:' e)
输出结果如下:
handle NameError:name 'ohmy' is not defined
上面的e就是异常对象本身,我们可以打印出异常对象里面存储的具体错误信息
3.4.捕获所有异常
有的时候,我们并不知道会抛出什么样的异常,但是我们并不希望有未知异常抛出的时候,程序被异常中止,这时候蜗牛可以捕获所以类型的异常,如下:
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())
3.5.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
3.6.else语句
在 Python 中,还有另一种异常处理结构,就是 try except else 语句,也就是在原来 try except 语句的基础上再添加一个 else 子句,其作用是指定当 try 块中没有发现异常时要执行的代码。换句话说,当 try 块中发现异常,则 else 块中的语句将不会被执行。
例如如下程序:
s = input('请输入除数:') try: result = 20 / int(s) print('20除以%s的结果是: %g' % (s , result)) except ValueError: print('值错误,您必须输入数值') except ArithmeticError: print('算术错误,您不能输入0') else: print('没有出现异常') print("程序继续运行")
上面程序为异常处理流程添加了 else 块,当程序中的 try 块没有出现异常时,程序就会执行 else 块。运行上面程序,如果用户输入导致程序中的 try 块出现了异常,则运行结果如下:
请输入除数:a
值错误,您必须输入数值
程序继续运行
如果用户输入让程序中的 try 块顺利完成,则运行结果如下:
请输入除数:3
20 除以3 的结果是:6.66667
没有出现异常
程序继续运行
如果else和finally同时存在,则else需要在finally之前,顺序如下:
try: print("Try block") except Exception as e: print("Except block") else: print("Else block") finally: print("Finally block")

浙公网安备 33010602011771号