python异常处理
Python使用try语句实现异常处理。try语句包围着可能引发异常的其他语句。try语句以关键字try开头,后续一个冒号(:)和一个可能在其中引发异常的代码。try语句可指定一个或多个except子句,它们紧接在try suite之后。每个except子句都指定了零个或多个异常类名,它们代表要由except子句处理的异常类型。可在except子句中指定一个标志符,程序用它引用被捕捉的异常对象。处理程序利用标识符从异常对象获取也异常有关的信息。如果except子句中没有指定异常类型,就称为"空白except子句"。这种子句会捕捉所有异常类型。在最后一个except子句之后,可选择性地添加一个else子句。如果try suite中的代码没有引发异常,就会执行else子句中的代码。如果try语句没有指定except子句,那就必须包含一个finally子句----该子句肯定会执行,无论是否发生异常。
在try语句中同时包括except和finally子句是语法错误,可接受的组合形式只有:
1 try:
...... #可能得到异常的语句
except #锁定是哪种异常 (可以有多个except语句) except
Exception,e:
#捕获所有异常信息传递给变量 e
...... #出现异常的处理方法
2 try:
......
except
.......
else
......
3 try:
......
finally #仅检查异常并做一些必要的清理工作 (仅能有一个finally语句)
........
一旦程序代码导致异常,或Python解释器检测到问题,代码或解释器就会“引发”一个异常。有的程序员将程序中发生异常的位置称为“引发点”。异常是一些类的对象,这些类都是从Exception类继承的。如果在一个try suite中发生异常,这个try suite会立即“超时”(即立即终止),程序控制权会移交给try suite之后的第一个except处理程序(如果有的话),接着解释器搜索可对这种异常类型进行处理的第一个except处理程序。解释器为了确定相匹配的except,需要将引发的异常的类型与每个except处理程序的异常类型比较,直到最终发现相匹配的为止。如类型完全一致,或引发的异常的类型是except处理程序的异常类型的一个派生类,就表明发生了匹配。如果try suite中没有发生异常,解释器将忽略用于try语句的异常处理程序,并执行try语句的else子句(如果有的话)。如果没有发生异常,或者某个except子句成功处理了异常,程序会从try语句之后的下一个语句恢复执行。如果在某个语句中发生了一个异常,但该语句不在一个try suite 中,而是一在一个函数中,那么包含那个语句的函数会立即终止,解释器会试图在(发出)调用(的)代码中查找一个封闭的try语句,这个过程称为“堆栈辗转开解”(Stacking Unwinding)。
----------------------------------------------------------------------------------------------
python shell
>>> open('abc.txt','r') Traceback (most recent call last): File "<stdin>", line 1, in <module> IOError: [Errno 2] No such file or directory: 'abc.txt'
打开一个不存在的文件abc.txt 文件,当系统找不到abc.txt 文件时,就会抛出给我们一个IOError类型的错误,No such file or directory:abc.txt (没有abc.txt这样的文件或目录)
Try...except...
假如,我们已经知道这种类型的错误,那么就可以通过一个异常扑捉来扑捉这个错误。我们可以通过try...except 来接收这个错误。打开文件写入:
try: open("abc.txt",'r') except IOError: pass
再来运行程序就会看不到任何错误,因为我们用except 接收了这个IOError错误。pass 表示实现了相应的实现,但什么也不做。
假如我不是打开一个文件,而是输出一个没有定义的变量呢?
try: print aa except IOError: pass
显然,在上面的代码中我并没有对aa 赋值,运行结果:
Traceback (most recent call last): File "/home/fnngj/py_se/tryy.py", line 3, in <module> print aa NameError: name 'aa' is not defined
我们已经用except 接收错误了,为什么错误还是还是抛出来了。如果你细心会发现这一次的错误类型是NameError ,而我接收类型是IOError ,所以要想接收这个print的错误,那么需要修改接收错误的类型为NameError
虽然,我知道print 语句是可能会抛一个NameError 类型的错误,虽然接收了这个类型错误,但我不知道具体的错误提示信息是什么。那么,我能不能把错误信息打印出来呢?当然可以:
try: print aa except NameError, msg: print msg
我们在接收错误类型的后面定义一个变量msg用于接收具体错误信息, 然后将msg接收的错误信息打印。再来运行程序:
name 'aa' is not defined
现在只打印了一行具体错误信息。
异常的抛出机制:
1、如果在运行时发生异常,解释器会查找相应的处理语句(称为handler).
2、要是在当前函数里没有找到的话,它会将异常传递给上层的调用函数,看看那里能不能处理。
3、如果在最外层(全局“main”)还是没有找到的话,解释器就会退出,同时打印出traceback以便让用户找到错误产生的原因。
注意:虽然大多数错误会导致异常,但一个异常不一定代表错误,有时候它们只是一个警告,有时候它们可能是一个终止信号,比如退出循环等。
try...finally...
try...finally...子句用来表达这样的情况:
我们不管线捕捉到的是什么错误,无论错误是不是发生,这些代码“必须”运行,比如文件关闭,释放锁,把数据库连接返还给连接池等。
创建文件poem.txt
tryf.py
import time try: f = file('poem.txt') while True: # our usual file-reading idiom line = f.readline() if len(line) == 0: break time.sleep(2) print line,
finally: f.close() print 'Cleaning up...closed the file'
运行程序(在windows命令提示符或linux终端下运行):
...$ python tryf.py abc efg ^CCleaning up...closed the file Traceback (most recent call last): File "tryy.py", line 18, in <module> time.sleep(2) KeyboardInterrupt
程序读poem.txt文件中每一行数据打印,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样做的原因是让程序运行得慢一些。在程序运行的时候,按Ctrl-c中断/取消程序。
我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。
到目前为止,我们只讨论了如何捕捉异常,那么如何抛出异常呢?
Raise抛出异常
使用raise来抛出一个异常: 主动抛出一个异常,想让程序停止,可以主动抛出一个异常,与exit相比:有明确的原因
tryr.py
#coding=utf-8
filename = raw_input('please input file name:')
if filename=='hello':
raise NameError('input file name error !')
程序要求用户输入一个文件名,如果用户输入的文件名是hello ,那么抛出一个NameError的异常,用户输入hello 和NameError异常之间没有任何必然联系,我只是人为的通过raise来这样定义,我当然也可以定义称TypeError ,但我定义的异常类型必须是python提供的。
---------------------------------------------------------------------------------------------------------------------------
1、try...except...语句
我们尝试读取用户的一段输入。按Ctrl-d,看一下会发生什么。
>>> s = raw_input('Enter something --> ')
Enter something --> Traceback (most recent call last):
File "<stdin>", line 1, in ?
EOFError
Python引发了一个称为EOFError
的错误,这个错误基本上意味着它发现一个不期望的 文件尾 (由Ctrl-d表示)
接下来,我们将学习如何处理这样的错误。
我们可以使用try..except
语句来处理异常。我们把通常的语句放在try-块中,而把我们的错误处理语句放在except-块中。
处理异常
#!/usr/bin/python
# Filename: try_except.pyimport
sys
try
:
s =
raw_input
(
'Enter something --> '
)
except
EOFError:
print
'\nWhy did you do an EOF on me?'
sys
.exit()
# exit the program
except
:
print
'\nSome error/exception occurred.'
# here, we are not exiting the program
print
'Done'
输出
$ python try_except.py
Enter something -->
Why did you do an EOF on me?
$ python try_except.py
Enter something --> Python is exceptional!
Done
如果有多重异常情况,那么我们可以写多个except 来解决问题.
2、try ... except...else语句
现在我们来说说这个else语句。Python中有很多特殊的else用法,比如用于条件和循环。放到try语句中,其作用其实也差不多:就是当没有检测到异常的时候,则执行else语句。举个例子大家可能更明白些:
>>> import syslog
>>> try:
... f = open("/root/test.py")
... except IOError,e:
... syslog.syslog(syslog.LOG_ERR,"%s"%e)
... else:
... syslog.syslog(syslog.LOG_INFO,"no exception caught\n")
...
>>> f.close()
3、finally子句
finally子句是无论是否检测到异常,都会执行的一段代码。我们可以丢掉except子句和else子句,单独使用try...finally,也可以配合except等使用。
例如2.2的例子,如果出现其他异常,无法捕获,程序异常退出,那么文件 f 就没有被正常关闭。这不是我们所希望看到的结果,但是如果我们把f.close语句放到finally语句中,无论是否有异常,都会正常关闭这个文件,岂不是很妙!
>>> import syslog
>>> try:
... f = open("/root/test.py")
... except IOError,e:
... syslog.syslog(syslog.LOG_ERR,"%s"%e)
... else:
... syslog.syslog(syslog.LOG_INFO,"no exception caught\n")
... finally:
>>> f.close()
-------------------------------------------------------------------------------------------------------
Python是面向对象语言,所以程序抛出的异常也是类。常见的Python异常有以下几个
python标准异常
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(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 | 用户代码生成的警告 |
Python官网异常类查询文档:
https://docs.python.org/2/library/exceptions.html#bltin-exceptions
http://www.runoob.com/python/python-exceptions.html