首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > perl python >

python错误处理常见异常

2012-10-08 
python异常处理常见错误来源:http://man.chinaunix.net/develop/python/python_howto/python_howto_progra

python异常处理常见错误
来源:
http://man.chinaunix.net/develop/python/python_howto/python_howto_program.htm

12.1. 知识点

Python中异常处理的样式及细节基于Modula-3语言,类似于c#和java。

Python使用try语句实现异常处理。try语句包围着可能引发异常的语句。try语句以关键字try 开头,后续一个冒号和一个可能在其中引发异常的代码块。try可指定一个或多个except子句,它们紧接 在try块后,每个except子句指定了零个或多上异常类名,它们代表要由except子句处理的异常类型。 可在except子句中指定一个标识答,程序用它引用被捕获的异常对象。处理程序利用标识符从异常对象 获取与异常有关的信息。如果except子句中没有指定异常类型,则会捕捉所有类型的异常。在最后一个 except子句之后,可选择性地添加一个else子句。如果try块中的代码没有引发异常,就会执行else 子句中的代码。如果try语句中没有指定except子句,那不必须包含一个finally子句,该子句肯定会执 行,无论是否发生异常。

异常是一些类的对象,这些类都是从Exception类继承的。如果有一个try块中发生异常,这个块会 立即终止,程序控制权会移交给try块后的第一个except处理程序。解释器为了确定相匹配的except,需 要将引发的异常类型与每个except类型比较,直到匹配为止。如果类型完全一致,或引发的异常类型是 except处理程序的异常类型的一个派生类,就表明发生了匹配。

如果try块中没有发生异常,解释器将忽略用于try语句的异常处理程序,并执行try语句的else子句 (如果有的话),如果没有发生异常,或某个except子句处理了这个异常,程序会从try语句之后的下一个 语句恢复执行。如果某个语句发生了异常,但该语句不在try块中,而是在一个函数中,那么包含这个语句的 函数会立即终止,解释器会试图在(发出)调用(的)代码中查找一个封闭的try语句,这个过程称为“堆栈 辗转开解”。

python使用“异常处理的终止模型”,因为引发异常的try块会在异常发生后立即“过期”。有的语言 使用“异常处理的恢复模型”,完成异常处理后,控制权会返回异常引发点,并从那个位置恢复执行。

尽管可在try块中包含任意语句,但通常只包含可能引发异常的语句。在else块中,则放置不会引发异 常的、而且只有在相应的try块中没有发生异常的前提下才应该执行的语句。

python的Exception异常类是一种层次结构,从Exception继承的4个类包括SystemExit,StopIteration, Warning以及StandardError。

python中不存在内存泄漏问题,解释器会自动进行“垃圾回收”。但解释器不能完全清除内存泄漏。只 要存在对一个对象的引用,解释器就会对其进行垃圾回收。所以,如果程序员偶然保留了不需要的对象引用, 仍会出现内存泄漏。

python异常处理机制提供了finally子句,只要程序控制进入相应的try块,就必然会执行这个finally 子句(无论try成功执行与否),所以finally是放置资源回收代码的理想地点。如果try块执行成功,则finally 会在try块终止后立即执行,如果try块发生异常,则会在导致异常的那一行之后,立即执行finally子句。

12.2. 良好的编程习惯

使每类问题都与一个命名得体的异常类关联,使程序结构清晰易读。

在创建程序员自定义异常类之前,应分析python层次结构中现有有异常类,看是否有可满足自已需要的类, 只有在程序需捕捉和处理与现有异常类型不同的新异常时,才定义新异常类。

12.3. 常见编程错误

退出程序可能导致资源(比如文件或网络连接)无法由其它程序使用。这称为“资源泄漏”。

在try语句中同时包括except和finally子句是语法错误。可接受的组合形式中有:try/except, try/except/else以及try/finally。

每个try块与其第一个except处理程序之间、两个except处理程序之间、最后一个except处理程 序与else子句之间或者try块和finally子句之间,不允许出现任何语句,否则是语法错误。

如果try语句既不包括finally语句,也不包括except语句,那就属于语法错误。如果try语句不包括 except子句,那么必须包括一个finally语句,如果try语句不包括finally语句,那么至少包括一个except子句。

在finally中引发异常是非常危险的,执行finally子句时,如果一个未被捕获的异常正在等候处理,而 finally又引发一个新的、未被该块捕获的异常,那么第一个异常就会丢失,新异常则传递给下一个封闭的try语句。

12.4. 测试和调试提示

在finally块中,必须将可能引发异常的代码封闭到一个try语句中,这样可避免丢失未捕捉的、 在finally块执行之前发生的异常。

traceback展示了自异常发生之时起,一个完整的函数调用堆栈。这样一来,程序员就可查看导致 异常的一系列函数调用。traceback中的信息包括辗转开解的函数名称:在其中定义了函数的那个文件的 名称以及程序遇到错误时的行号。traceback中的最后一个行号是“引发点”(即初始异常引发的位置)。 在它之前的一系列行号则是在traceback中每个函数的调用位置。

阅读traceback报告时,请按从下到上的顺序,先读错误消息。然后,向上阅读traceback剩余部 份,查找报告中的第一个行号。通常,这就是导致异常的位置。

12.5. 软件工程知识

从设计阶段初期,就要将异常处理策略考虑到系统中。系统实现后再添加有效的异常处理是很难的。

过去,程序员用多种技术来实现错误处理代码。异常处理则提供了一种统一的机制来处理错误, 因此,当许多程序员从事同一个大型项目时,相互之间可轻松理解对方的错误处理代码。

通常不要将异常显式地应用于常规控制流程(虽然也可这样做),否则会因为较难跟踪随后发生 的大量异常,导致程序变得难以阅读和维护。

要精心选择放入try块中的代码,其中应有好几个语句都可能引发异常。尽量避免为可能引发异常 的每个语句都单独使用一个try语句。但是,要想确保正确的异常处理,每个try语句都应尽可能封装一 个足够小的代码区,这样一来,一旦发生异常,就可确切把握当时的背景,使except处理程序能正确地 处理异常。如果一个try块中的多个语句都可以引发相同的异常类型,就必须用多个try语句确定每个异 常的背景。

在一个except子句中,可以指定多个异常,只需在圆括号中使用由逗号分隔的一个异常名称序列 即可,要用except子句指定我个异常,这些异常应以某种形式相互关联(如都是因算术计算错误而引发 的异常)。将相关的异常分为一组,再为每一组单独使用一个except子句。

引发异常的代码要先释放代码中获取的任何资源,再引发异常。

如果try语句指定了一个finally子句,那么即使try块由一个return语句终止,finally子句的 代码也会。执行完成后,才轮到通过return返回调用代码。

12.6. 性能提示

如果没有发生异常,异常处理代码对性能的影响极微(或者说根本没有),所以,相较于在程序逻 辑中混合了错误处理逻辑的程序,实现了异常处理的程序效率更高。

热点排行