python学习08-错误和异常

来源:互联网 发布:sql界面 编辑:程序博客网 时间:2024/06/05 04:11

错误和异常
异常
对异常的最好描述是: 它是因为程序出现了错误而在正常控制流以外采取的行为. 这个行为又分为两个阶段: 首先是引起异常发生的错误, 然后是检测(和采取可能的措施)阶段.
异常可以通过 try 语句来检测. 任何在 try 语句块里的代码都会被监测, 检查有无异常发生.
try 语句有两种主要形式: try-except 和 try-finally . 这两个语句是互斥的, 也就是说你只 能 使 用 其 中 的 一 种 . 一 个 try 语 句 可 以 对 应 一 个 或 多 个 except 子 句 , 但 只 能 对 应 一 个finally 子句, 或是一个 try-except-finally 复合语句.
你可以使用 try-except 语句检测和处理异常. 你也可以添加一个可选的 else 子句处理没有探测到异常的时执行的代码. 而 try-finally 只允许检测异常并做一些必要的清除工作(无论发生错误与否), 没有任何异常处理设施. 正如你想像的,复合语句两者都可以做到.
在程序运行时, 解释器尝试执行 try 块里的所有代码, 如果代码块完成后没有异常发生, 执行流就会忽略 except 语句继续执行. 而当 except 语句所指定的异常发生后, 我们保存了错误的原因, 控制流立即跳转到对应的处理器( try 子句的剩余语句将被忽略)
忽略代码, 继续执行, 和向上移交
try 语句块中异常发生点后的剩余语句永远不会到达(所以也永远不会执行). 一旦一个异常被引发, 就必须决定控制流下一步到达的位置. 剩余代码将被忽略, 解释器将搜索处理器, 一旦找到,就开始执行处理器中的代码.
如果没有找到合适的处理器, 那么异常就向上移交给调用者去处理, 这意味着堆栈框架立即回到之前的那个. 如果在上层调用者也没找到对应处理器, 该异常会继续被向上移交, 直到找到合适处理器. 如果到达最顶层仍然没有找到对应处理器, 那么就认为这个异常是未处理的, Python 解释器会显示出跟踪返回消息, 然后退出.
我们还可以在一个 except 子句里处理多个异常. except 语句在处理多个异常时要求异常被放在一个元组里.
捕获所有异常
我们没有指定任何要捕获的异常 - 这不会给我们任何关于可能发生的错误的信息. 另外它会捕获所有异常, 你可能会忽略掉重要的错误, 正常情况下这些错误应该让调用者知道并做一定处理.最后, 我们没有机会保存异常发生的原因.
关于异常的一部分内容在 Python 2.5 有了一些变化. 异常被迁移到了 new-style class 上,启用了一个新的”所有异常的母亲”, 这个类叫做 BaseException , 异常的继承结构有了少许调整,为了让人们摆脱不得不除创建两个处理器的惯用法. KeyboardInterrupt 和 SystemExit 被从Exception 里移出, 和 Exception 平级:
- BaseException
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (all other current built-in exceptions) 所有当前内建异常
如果你确实需要捕获所有异常, 那么你就得使用新的 BaseException
异常参数
异常也可以有参数, 异常引发后它会被传递给异常处理器. 当异常被引发后参数是作为附加帮助信息传递给异常处理器的.
要想访问提供的异常原因, 你必须保留一个变量来保存这个参数. 把这个参数放在except 语句后, 接在要处理的异常后面.
else 子句
else 没有太多的不同:在 try 范围中没有异常被检测到时,执行 else 子句.
finally 子句是无论异常是否发生,是否捕捉都会执行的一段代码.你可以将 finally 仅仅配合try 一起使用,也可以和 try-except(else 也是可选的)一起使用.
try-finally 语句
另一种使用 finally 的方式是 finally 单独和 try 连用.这个 try-finally 语句和 try-except区别在于它不是用来捕捉异常的.作为替代,它常常用来维持一致的行为而无论异常是否发生.我们得知无论 try 中是否有异常触发,finally 代码段都会被执行.
with 语句
类似 try-except-finally , with 语句也是用来简化代码的,这与用 try-except 和 try-finally所想达到的目的前后呼应.try-except 和 try-finally 的一种特定的配合用法是保证共享的资源的唯一分配,并在任务结束的时候释放它.比如文件(数据,日志,数据库等等),线程资源,简单同步,数据库连接,等等. with 语句的目标就是应用在这种场景.
with 语法的基本用法
with context_expr [as var]:
with_suite
看起来如此简单,但是其背后还有一些工作要做.这并不如看上去的那么容易,因为你不能对Python 的任意符号使用 with 语句.它仅能工作于支持上下文管理协议(context managementprotocol)的对象.这显然意味着只有内建了”上下文管理”的对象可以和 with 一起工作.
with open(‘/etc/passwd’, ‘r’) as f:
for eachLine in f:
# …do stuff with eachLine or f…
这个代码片段干了什么呢…嗯,这是 Python,因而你很可能的已经猜到了.它会完成准备工作,比如试图打开一个文件,如果一切正常,把文件对象赋值给 f.然后用迭代器遍历文件中的每一行,当完成时,关闭文件.无论的在这一段代码的开始,中间,还是结束时发生异常,会执行清理的代码,此外文件仍会被自动的关闭.
触发异常 raise 语句
rasie 一般的用法是:
raise [SomeException [, args [, traceback]]]
第一个参数,SomeExcpetion,是触发异常的名字.如果有,它必须是一个字符串,类或实例(详见下文).如果有其他参数(arg 或 traceback),就必须提供 SomeExcpetion.
第二个符号为可选的 args(比如参数,值),来传给异常.这可以是一个单独的对象也可以是一个对象的元组.当异常发生时,异常的参数总是作为一个元组传入.如果 args 原本就是元组,那么就将其传给异常去处理;如果 args 是一个单独的对象,就生成只有一个元素的元组(就是单元素元组).大多数情况下,单一的字符串用来指示错误的原因.如果传的是元组,通常的组成是一个错误字符串,一个错误编号,可能还有一个错误的地址,比如文件,等等.
最后一项参数,traceback,同样是可选的(实际上很少用它),如果有的话,则是当异常触发时新生成的一个用于异常-正常化(exception—normally)的追踪(traceback)对象.当你想重新引发异常时,第三个参数很有用(可以用来区分先前和当前的位置).如果没有这个参数,就填写 None.
断言 言可以简简单单的想象为 raise-if 语句(更准确的说是raise-if-not 语句).测试一个表达式,如果返回值是假,触发异常.
ssert 的语法如下: assert expression[, arguments]
AssertionError 异常和其他的异常一样可以用 try-except 语句块捕捉,但是如果没有捕捉,它将终止程序运行而且提供一个traceback:
Python 内建异常
BaseException 所有异常的基类
SystemExit python 解释器请求退出
KeyboardInterrupt 用户中断执行(通常是输入^C)
Exception 常规错误的基类
StopIteration 迭代器没有更多的值
GeneratorExit 生成器(generator)发生异常来通知退出
SystemExit Python 解释器请求退出
StandardError 所有的内建标准异常的基类
ArithmeticError 所有数值计算错误的基类
FloatingPointError 浮点计算错误
OverflowError 数值运算超出最大限制
ZeroDivisionError 除(或取模)零 (所有数据类型)
AssertionError 断言语句失败
AttributeError 对象没有这个属性
EOFError 没有内建输入,到达 EOF 标记
EnvironmentError 操作系统错误的基类
IOError 输入/输出操作失败
OSError 操作系统错误
WindowsError Windows 系统调用失败
ImportError 导入模块/对象失败
KeyboardInterrupt 用户中断执行(通常是输入^C)
LookupError 无效数据查询的基类
IndexError 序列中没有没有此索引(index)
KeyError 映射中没有这个键
MemoryError 内存溢出错误(对于 Python 解释器不是致命的)
NameError 未声明/初始化对象 (没有属性)
UnboundLocalErrorh 访问未初始化的本地变量
ReferenceError e 弱引用(Weak reference)试图访问已经垃圾回收了的对象
RuntimeError 一般的运行时错误
NotImplementedError 尚未实现的方法
SyntaxError Python 语法错误
IndentationError 缩进错误
TabError Tab 和空格混用
SystemError 一般的解释器系统错误
TypeError 对类型无效的操作
ValueError 传入无效的参数
UnicodeError Unicode 相关的错误
UnicodeDecodeError Unicode 解码时的错误
UnicodeEncodeError Unicode 编码时错误
UnicodeTranslateError Unicode 转换时错误
Warning 警告的基类
DeprecationWarning 关于被弃用的特征的警告
FutureWarning 关于构造将来语义会有改变的警告
OverflowWarning 旧的关于自动提升为长整型(long)的警告
PendingDeprecationWarning 关于特性将会被废弃的警告
RuntimeWarning 可疑的运行时行为(runtime behavior)的警告
SyntaxWarning 可疑的语法的警告
UserWarning 用户代码生成的警告
所有的标准/内建异常都是从根异常派生的.目前,有 3 个直接从 BaseException 派生的异常子类:SystemExit,KeyboardInterrupt 和 Exception.其他的所有的内建异常都是 Exception 的子类.
异常和 sys 模块
另一种获取异常信息的途径是通过 sys 模块中 exc_info()函数. 此功能提供了一个 3 元组(3-tuple)的信息, 多于我们单纯用异常参数所能获得.
我们从 sys.exc_info()得到的元组中是:
z exc_type: 异常类
z exc_value: 异常类的实例
z exc_traceback: 追踪(traceback)对象
我们所熟悉的前两项:实际的异常类, 和这个异常类的实例(和在上一节我们讨论的异常参数是一样的) . 第三项, 是一个新增的追踪(traceback)对象. 这一对象提供了的发生异常的上下文.它包含诸如代码的执行帧,异常发生时的行号等信息.

0 0
原创粉丝点击