返回介绍

第35章 异常的设计

发布于 2024-01-29 22:24:14 字数 2068 浏览 0 评论 0 收藏 0

这一章包括了异常设计的话题以及常用例子的集合,再加上这一部分的陷阱和练习题。由于本章是本书基础话题部分的收尾,因此也会简单介绍一下开发工具,帮助你从Python初学者转变成为Python应用开发者。

嵌套异常处理器

到目前为止,我们的例子都只使用了单一的try语句来捕捉异常,如果try中还有try,那会发生什么事情呢?就此而言,如果try调用一个会执行另一个try的函数,这代表了什么意思呢?从技术角度上来讲,从语法和代码运行时的控制流程来看,try语句是可以嵌套的。

如果你知道Python会在运行时将try语句放入堆栈,这两种情况就可以理解了。当发生异常时,Python会回到最近进入、具有相符except分句的try语句。因为每个try语句都会留下标识,Python可检查堆栈的标识,从而跳回到较早的try。这种处理器的嵌套化,就是我们所谈到的异常向上传递至较高的处理器的意思:这类处理器就是在程序执行流程中较早进入的try语句。

图35-1说明嵌套的try/except语句在运行时所发生的事情。进入try代码块的代码量可能很大(例如,它可能包含了函数调用),而且通常会启用正在监视相同异常的其他代码。当异常最终引发时,Python会跳回到匹配该异常、最近进入的try语句,执行该语句的except分句,然后在try语句后继续下去。

一旦异常被捕捉,其生命就结束:控制权不会跳回所有匹配这个异常、相符的try语句;只有第一个try有机会对它进行处理。如图35-1所示,函数func2中的raise语句会把控制权返还func1中的处理器,然后程序再在func1中继续下去。

图 35-1 嵌套的try/except语句:当异常引发时(由你或由Python引起),控制权会跳回具有相符的except子句、最近进入的try语句,而程序会在try语句后继续执行下去。except子句会拦截并停止异常,这里就是你处理异常并从中恢复的地方

与之相对比的是,当try/finally语句嵌套且异常发生时,每个finally代码块都会执行:Python会持续把异常往上传递到其他try语句上,而最终可能达到顶层默认处理器(标准出错消息打印器)。如图35-2所示,finally子句不会终止异常,而是指明异常传播过程中,离开每个try语句之前要执行的代码。如果异常发生时,有很多try/finally都在活动,它们就都会运行,除非有个try/except在这个过程中捕捉某处该异常。

图 35-2 嵌套的try/finally:当异常在这里引发时,控制权会回到最近进入的try去执行其finally语句,异常会持续传播到所有激活状态下try语句的finally,直到最终抵达默认顶层处理器,在那里打印出错消息。Finally子句会拦截(但不会停止)异常:只是定义了离开前要执行的动作而已

换句话说,引发异常时,程序去向何方完全取决于异常在何处发生:这是脚本运行时控制流程的函数,而不仅仅是其语法。异常的传递,基本上就是回到处理先前进入但尚未离开的try。只要控制权碰到相符except子句,传递就会停止,而通过finally子句时就不会。

例子:控制流程嵌套

让我们分析一个例子,让这个嵌套的概念更为具体。下面的模块文件nestexc.py定义了两个函数。action2是写成要触发异常(做数字和序列的加法),而action1把action2调用封装在try处理器内,以捕捉异常。

那么,文件底端的顶层模块代码,也在try处理器中包装了action1调用。当action2触发TypeError异常时,就有两个激活的try语句:一个在action1内,另一个在模块文件顶层。Python会挑选并执行具有相符except、最近的try,而在这个例子中就是action1中的try。

正如我所提到过的,异常最后的所在之处,取决于程序运行时的控制流程。因此,想要知道你要去哪里,就需要知道你在哪里。就这个例子而言,异常在哪里进行处理是控制流程的函数,而不是语句的语法。然而,我们也可以用语法把异常处理器嵌套化——等一下会看与其等效的情况。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文