Python_10-异常处理
目录:
1.1 python标准异常
1.2 简介
1.3 try语句
1.3.1 使用try和except语句来捕获异常
1.3.2 该种异常处理语法的规则
1.3.3 使用try跟finally
1.4 用raise语句手工引发一个异常
1.5 采用traceback(跟踪)模块查看异常
1.6 采用sys模块回溯最后的异常
1.7 异常处理的一些其它用途
1.8 两个特殊的处理异常的简便方法
1.8.1 断言(assert)
1.8.2 上下文管理(with语句)
1.1 python标准异常
异常名称 |
描述 |
BaseException |
所有异常的基类 |
SystemExit |
解释器请求退出 |
KeyboardInterrupt |
用户中断执行(通常是输入^C) |
Exception |
常规错误的基类 |
StopIteration |
迭代器没有更多的值 |
GeneratorExit |
生成器(generator)发生异常来通知退出 |
StandardError |
所有的内建标准异常的基类 |
ArithmeticError |
所有数值计算错误的基类 |
FloatingPointError |
浮点计算错误 |
OverflowError |
数值运算超出最大限制 |
ZeroDivisionError |
除(或取模)零 (所有数据类型) |
AssertionError |
断言语句失败 |
AttributeError |
对象没有这个属性 |
EOFError |
没有内建输入,到达EOF 标记 |
EnvironmentError |
操作系统错误的基类 |
IOError |
输入/输出操作失败 |
OSError |
操作系统错误 |
WindowsError |
系统调用失败 |
ImportError |
导入模块/对象失败 |
KeyboardInterrupt |
用户中断执行(通常是输入^C) |
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 |
用户代码生成的警告 |
1.2 简介
1.Python的异常处理能力是很强大的,可向用户准确反馈出错信息。
2.在Python中,异常也是对象,可对它进行操作。
3.所有异常都是基类Exception的成员。
4.所有异常都从基类Exception继承,而且都在exceptions模块中定义。
Python自动将所有异常名称放在内建命名空间中,所以程序不必导入exceptions模块即可使用异常。一旦引发而且没有捕捉SystemExit异常,程序执行就会终止。如果交互式会话遇到一个未被捕捉的SystemExit异常,会话就会终止。
try: try_suite except Exception1,Exception2,...,Argument: exception_suite ...... #other exception block else: no_exceptions_detected_suite finally: always_execute_suite #1.可选语句:else语句,finally语句; #2.可以不要exception语句,而保留finally语句。
1.3 try语句
1.3.1 使用try和except语句来捕获异常
try: block except [exception,[data…]]: block 语法2: try: block except [exception,[data...]]: block else: block
该种异常处理语法的规则:
1.执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句。
2.如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句。
3.如果引发的异常不匹配第一个except,则会搜索第二个except,允许编写的except数量没有限制。
4.如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。
5.如果没有发生异常,则执行else块代码。
eg:
#!/usr/bin/python # Filename: try_except.py import sys try: s = input('Enter something --> ') except EOFError:#处理EOFError类型的异常 print '/nWhy did you do an EOF on me?' sys.exit() # 退出程序 except: #处理其它的异常 print '/nSome error/exception occurred.' print 'Done'
1.3.2 该种异常处理语法的规则
·执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句。
·如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句。
·如果引发的异常不匹配第一个except,则会搜索第二个except,允许编写的except数量没有限制。
·如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。
·如果没有发生异常,则执行else块代码。
eg:
try: f = open("file.txt","r") except IOError, e: print e
捕获到的IOError错误的详细原因会被放置在对象e中,然后运行该异常的except代码块
捕获所有的异常
try: a=b b=c except Exception,ex: print Exception,":",ex
使用except子句需要注意的事情,就是多个except子句截获异常时,如果各个异常类之间具有继承关系,则子类应该写在前面,否则父类将会直接截获子类异常。放在后面的子类异常也就不会执行到了。
eg:
try: floatnum = float(input("Please input a float:")) intnum = int(floatnum) print(100/intnum) except ZeroDivisionError: print("Error:you must input a float num which is large or equal then 1!") except ValueError: print("Error:you must input a float num!")
except子句后面那个Argument
这个Argument其实是一个异常类的实例,包含了来自异常代码的诊断信息。也就是说,如果你捕获了一个异常,你就可以通过这个异常类的实例来获取更多的关于这个异常的信息。
type可以查看异常类实例的类型。
1.3.3 使用try跟finally
try: block finally: block
该语句的执行规则是:
·执行try下的代码。
·如果发生异常,在该异常传递到下一级try时,执行finally中的代码。
·如果没有发生异常,则执行finally中的代码。
第二种try语法在无论有没有发生异常都要执行代码的情况下是很有用的。例如我们在python中打开一个文件进行读写操作,我在操作过程中不管是否出现异常,最终都是要把该文件关闭的。
这两种形式相互冲突,使用了一种就不允许使用另一种,而功能又各异。
举例:
当你正在读文件或还未关闭文件时发生了异常该怎么办呢?你应该使用try...finally语句以释放资源。
示例如下:
#!/usr/bin/python # Filename: finally.py import time try: f = file('d:\\f.txt') while True: # 读文件的一般方法 line = f.readline() if len(line) == 0: break time.sleep(2)#每隔两秒输出一行 print line, finally: f.close() print 'Cleaning up...closed the file'
1.4 用raise语句手工引发一个异常
raise [exception[,data]]
在Python中,要想引发异常,最简单的形式就是输入关键字raise,后跟要引发的异常的名称。异常名称标识出具体的类:Python异常是那些类的对象。执行raise语句时,Python会创建指定的异常类的一个对象。raise语句还可指定对异常对象进行初始化的参数。为此,请在异常类的名称后添加一个逗号以及指定的参数(或者由参数构成的一个元组)。
eg:
try: raise MyError #自己抛出一个异常 except MyError: print 'a error' raise ValueError,'invalid argument'
#捕捉到的内容为: #type = VauleError #message = invalid argument
1.5 采用traceback(跟踪)模块查看异常
发生异常时,Python能"记住"引发的异常以及程序的当前状态。Python还维护着traceback(跟踪)对象,其中含有异常发生时与函数调用堆栈有关的信息。记住,异常可能在一系列嵌套较深的函数调用中引发。程序调用每个函数时,Python会在"函数调用堆栈"的起始处插入函数名。一旦异常被引发,Python会搜索一个相应的异常处理程序。如果当前函数中没有异常处理程序,当前函数会终止执行,Python会搜索当前函数的调用函数,并以此类推,直到发现匹配的异常处理程序,或者Python抵达主程序为止。这一查找合适的异常处理程序的过程就称为"堆栈辗转开解"(Stack Unwinding)。解释器一方面维护着与放置堆栈中的函数有关的信息,另一方面也维护着与已从堆栈中"辗转开解"的函数有关的信息。
try: block except: traceback.print_exc()
1.6 采用sys模块回溯最后的异常
另一种获取异常信息的途径是通过sys模块中的exc_info()函数。该函数回返回一个三元组:(异常类,异常类的实例,跟踪记录对象)
import sys try: block except: info=sys.exc_info() print info[0],":",info[1]
或者
import sys tp,val,td = sys.exc_info() #sys.exc_info()的返回值是一个tuple, (type, value/message, traceback) #这里的type ---- 异常的类型 #value/message ---- 异常的信息或者参数 #traceback ---- 包含调用栈信息的对象。
从这点上可以看出此方法涵盖了traceback.
eg:
try: 1/0 except: import sys tuple = sys.exc_info() print(tuple) #输出: #(<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero',), <traceback object at 0x02339760>)
1.7 异常处理的一些其它用途
除了处理实际的错误条件之外,对于异常还有许多其它的用处。在标准 Python 库中一个普通的用法就是试着导入一个模块,然后检查是否它能使用。导入一个并不存在的模块将引发一个ImportError异常。你可以使用这种方法来定义多级别的功能――依靠在运行时哪个模块是有效的,或支持多种平台 (即平台特定代码被分离到不同的模块中)。
你也能通过创建一个从内置的 Exception 类继承的类定义你自己的异常,然后使用 raise 命令引发你的异常。如果你对此感兴趣,请看进一步阅读的部分。
下面的例子演示了如何使用异常支持特定平台功能。代码来自getpass模块,一个从用户获得口令的封装模块。获得口令在 UNIX、Windows 和 Mac OS 平台上的实现是不同的,但是这个代码封装了所有的不同之处。
例 支持特定平台功能
# Bind the name getpass to the appropriate function try: import termios, TERMIOS except ImportError: try: import msvcrt except ImportError: try: from EasyDialogs import AskPassword except ImportError: getpass = default_getpass else: getpass = AskPassword else: getpass = win_getpass else: getpass = unix_getpass
termios是 UNIX 独有的一个模块,它提供了对于输入终端的底层控制。如果这个模块无效 (因为它不在你的系统上,或你的系统不支持它),则导入失败,Python 引发我们捕捉的 ImportError 异常。如果没有 termios,则试试 msvcrt,它是Windows 独有的一个模块,可以提供在 Microsoft Visual C++ 运行服务中的许多有用的函数的一个API。如果导入失败,Python 会引发我们捕捉的 ImportError 异常。如果前两个不能工作,我们试着从 EasyDialogs 导入一个函数,它是 Mac OS 独有的一个模块,提供了各种各样类型的弹出对话框。再一次,如果导入失败,Python 会引发一个我们捕捉的 ImportError 异常。
这些平台特定的模块没有一个有效 (有可能,因为 Python 已经移植到了许多不同的平台上了),所以我们需要回头使用一个缺省口令输入函数 (这个函数定义在 getpass 模块中的别的地方)。注意我们在这里所做的:我们将函数 default_getpass 赋给变量 getpass。如果你读了官方 getpass 文档,它会告诉你 getpass 模块定义了一个 getpass 函数。它是这样做的:通过绑定 getpass 到正确的函数来适应你的平台。然后当你调用 getpass 函数时,你实际上调用了平台特定的函数,是这段代码已经为你设置好的。你不需要知道或关心你的代码正运行在何种平台上;只要调用 getpass,则它总能正确处理。
一个 try...except 块可以有一条 else 子句,就像 if 语句。如果在 try 块中没有异常引发,然后 else 子句被执行。在本例中,那就意味着如果 from EasyDialogs import AskPassword 导入可工作,所以我们应该绑定 getpass 到 AskPassword 函数。其它每个 try...except 块有着相似的 else 子句,当我们发现一个 import 可用时,就绑定 getpass 到适合的函数。
1.8 两个特殊的处理异常的简便方法
1.8.1 断言(assert)
assert expression[,reason]
其中assert是断言的关键字。执行该语句的时候,先判断表达式expression,如果表达式为真,则什么都不做;如果表达式不为真,则抛出异常。reason跟我们之前谈到的异常类的实例一样。
assert len('police') == len('polite') assert 3==3 assert 3==4,"3 is not equal 4!" #输出: #AssertionError: 3 is not equal 4!
如果assert后面的表达式为真,则什么都不做,如果不为真,就会抛出AssertionError异常,而且我们传进去的字符串会作为异常类的实例的具体信息存在。其实,assert异常也可以被try块捕获:
try: assert 3 == 4 , "3 is not equal 4!" except AssertionError as reason: print("%s:%s"%(reason.__class__.__name__,reason)) #输出: #AssertionError:3 is not equal 4!
1.8.2 上下文管理(with语句)
如果你使用try, except, finally代码仅仅是为了保证共享资源(如文件,数据)的唯一分配,并在任务结束后释放它,那么可以使用with语句。
这个with语句可以让你从try, except, finally中解放出来!语法如下:
with context_expr [as var]: with_suite
eg:
with open('/root/test.py') as f: for line in f: print line
上面这几行代码干了什么?
(1)打开文件/root/test.py
(2)将文件对象赋值给 f
(3)将文件所有行输出
(4)无论代码中是否出现异常,Python都会为我们关闭这个文件,我们不需要关心这些细节。
使用with语句来使用这些共享资源,我们不用担心会因为某种原因而没有释放他。但并不是所有的对象都可以使用with语句,只有支持上下文管理协议(context management protocol)的对象才可以。
下列对象支持该协议:
file decimal.Context thread.LockType threading.Lock threading.RLock threading.Condition threading.Semaphore threading.BoundedSemaphore