- 译者序
- 前言
- 第1章 问答环节
- 第2章 Python 如何运行程序
- 第3章 如何运行程序
- 第4章 介绍 Python 对象类型
- 第5章 数字
- 第6章 动态类型简介
- 第7章 字符串
- 第8章 列表与字典
- 第9章 元组、文件及其他
- 第10章 Python 语句简介
- 第11章 赋值、表达式和打印
- 第12章 if 测试和语法规则
- 第13章 while 和 for 循环
- 第14章 迭代器和解析,第一部分
- 第15章 文档
- 第16章 函数基础
- 第17章 作用域
- 第18章 参数
- 第19章 函数的高级话题
- 第20章 迭代和解析,第二部分
- 第21章 模块:宏伟蓝图
- 第22章 模块代码编写基础
- 第23章 模块包
- 第24章 高级模块话题
- 第25章 OOP:宏伟蓝图
- 第27章 更多实例
- 第28章 类代码编写细节
- 第29章 运算符重载
- 第30章 类的设计
- 第31章 类的高级主题
- 第32章 异常基础
- 第34章 异常对象
- 第35章 异常的设计
- 第36章 Unicode 和字节字符串
- 字符串基础知识
- Python 的字符串类型
- 文本和二进制文件
- Python 3.0 中的字符串应用
- 转换
- 编码 Unicode 字符串
- 编码非ASCII文本
- 编码和解码非ASCII文本
- 其他 Unicode 编码技术
- 转换编码
- 在 Python 2.6 中编码 Unicode 字符串
- 源文件字符集编码声明
- 使用 Python 3.0 Bytes 对象
- 序列操作
- 创建 bytes 对象的其他方式
- 混合字符串类型
- 使用 Python 3.0(和 Python 2.6)bytearray 对象
- 使用文本文件和二进制文件
- Python 3.0 中的文本和二进制模式
- 类型和内容错误匹配
- 使用 Unicode 文件
- 在 Python 3.0 中处理 BOM
- Python 2.6 中的 Unicode 文件
- Python 3.0 中其他字符串工具的变化
- Struct二进制数据模块
- pickle对象序列化模块
- XML解析工具
- 本章小结
- 本章习题
- 习题解答
- 第37章 管理属性
- 第38章 装饰器
- 第39章 元类
- 附录A 安装和配置
- 附录B 各部分练习题的解答
- 作者介绍
- 封面介绍
第33章 异常编码细节
注意:此前的一点常规提示是:异常的内容近年来有了一些变化。从Python 2.5起,finally子句可以同样出现在try语句以及except和else语句中(此前,它们不能组合)。此外,从Python 3.0和Python 2.6开始,新的with环境管理器语句成为正式的,并且用户定义的异常现在必须编写为类实例。此外,Python 3.0支持raise语句和except子句的略微修改的语法。我们将在本书这一版本中关注Python 2.6和Python 3.0中的异常状态,但是,由于你仍然很可能在代码中看到最初的技术,因此,一路上我们会指出在此领域中有哪些发展变化。
try/except/else语句
既然了解了基础的知识,让我们来看一些细节。下列讨论中,本书把try/except/else和try/finally当成独立的语句进行介绍,因为它们是不同角色,在Python 2.5以前都无法合并。就像你所见到的一样,在Python 2.5中,except和finally可以混在一个try语句中。分别探索过这两种原始形式后,再说明这种改变的含义。
try是复合语句,它的最完整的形式如下所示。首先是以try作为首行,后面紧跟着(通常)缩进的语句代码,然后是一个或多个except分句来识别要捕捉的异常,最后是一个可选的else分句。try、except以及else这些关键字会缩进在相同的层次(也就是垂直对齐)。为了方便参考,以下是其在Python 3.0中的一般格式。
在这个语句中,try首行底下的代码块代表此语句的主要动作:试着执行的程序代码。Except子句定义try代码块内引发的异常的处理器,而else子句(如果编写了的话)则是提供没发生异常时要执行的处理器。在这里的<data>元素和raise语句功能有关,本章稍后会进行讨论。
以下是try语句的运行方式。当try语句启动时,Python会标识当前的程序环境,这样一来,如果有异常发生时,才能返回这里。try首行下的语句会先执行。接下来会发生什么事情,取决于try代码块语句执行时是否引发异常。
·如果try代码块语句执行时的确发生了异常,Python就跳回try,执行第一个符合引发异常的except子句下面的语句。当except代码块执行后(除非except代码块引发了另一异常),控制权就会到整个try语句后继续执行。
·如果异常发生在try代码块内,没有符合的except子句,异常就会向上传递到程序中的之前进入的try中,或者如果它是第一条这样的语句,就传递到这个进程的顶层(这会使Python终止这个程序并打印默认的出错消息)。
·如果try首行底下执行的语句没有发生异常,Python就会执行else行下的语句(如果有的话),控制权会在整个try语句下继续。
换句话说,except分句会捕捉try代码块执行时所发生的任何异常,而else子句只在try代码块执行时不发生异常才会执行。
except子句是专注于异常处理器的:捕捉只在相关try代码块中的语句所发生的异常。尽管这样,因为try代码块语句可以调用写在程序其他地方的函数,异常的来源可能在try语句自身之外。第35章探索try嵌套化时,会再多介绍一些关于这方面的内容。
try语句分句
编写try语句时,有一些分句可以在try语句代码块后出现。表33-1列出所有可能形式:至少会使用其中一种。本书已经介绍过一些表33-1列出的形式:正如你所知道的那样,except分句会捕捉异常,finally分句最后一定会执行,而如果没遇上异常,else分句就会执行。
从语法上来讲,except分句数目没有限制,但是应该只有一个else。在Python2.4中,finally必须单独出现(没有else或except),其实这是不同的语句。然而,从Python 2.5开始,finally可出现在except和else所在的同一个try语句中了(在本章中,当我们遇到统一的try语句的时候,还会更多地讨论排序规则)。
当我们见到raise语句时,就会探索具有额外数据的部分。它们提供了对作为异常引发的对象的访问。
表33-1中第一和第四项是新的。
·except子句没列出异常名称(except:)时,捕捉没在try语句内预先列出的所有异常。
·except子句以括号列出一组异常[except(e1,e2,e3):]会捕捉所列出的任何异常。
因为Python会从头到尾检查except子句,在某个try中寻找是否有相符者,所以括号版本就像是每个异常列在其except子句内,但是语句主体只需编写一次而已。以下是多个except子句的例子,示范处理器的具体化。
在这个例子中,如果action函数执行时,引发了异常,Python会回到try,并搜索第一个和异常名称相符的except。Python会从头到尾以及由左至右查看except子句,然后执行第一个相符的except下的语句。如果没有符合的,异常会向这个try外传递。注意:只有当action中没有发生异常时,else才会执行,当没有相符except的异常发生时,则不会执行。
如果想要编写通用的“捕捉一切”分句,空的except就可以做到。
空的except子句是一种通用功能:因为这是捕捉任何东西,可让处理器通用化或具体化。在某些场合下,比起列出的try中所有可能异常来说,这种形式反而更方便一些。例如,下面是捕捉一切,但没列出任何事件的例子。
不过,空except也会引发一些设计的问题:尽管方便,也可能捕捉和程序代码无关、意料之外的系统异常,而且可能意外拦截其他处理器的异常。例如,在Python中,即便是系统离开调用,也会触发异常,而你通常会想让这些事件通过。这一部分末尾会再谈这个陷阱。就目前而言,要小心使用。
Python 3.0引入了一个替代方案来解决这些问题之一——捕获一个名为Exception的异常几乎与一个空的except具有相同的效果,但是,忽略和系统退出相关的异常:
这与空的except具有大多相同的便利性,但是,几乎同样具有危险性。我们将在下一章介绍这种形式如何发挥其魔力,在我们学习异常类的时候。
注意:版本差异提示:Python 3.0要求表33-1中列出的except E as V:处理器子句形式,并且本书中使用该形式,而不是旧的except E,V:形式。后一种形式在Python 2.6中仍然可用(但是不推荐使用):如果使用它,它将会转换为前者。做出这一改变,是剔除把旧的形式与两种替代的异常搞混淆的错误,这两种替代形式在Python 2.6中相应地编码为except(E1,E2):。由于Python 3.0只支持as形式,不管是否使用圆括号,值都会解释为替代的异常以供捕获。这一修改还改变了作用域规则:使用新的as语法,变量V在except语句块的末尾删除。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论