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
posted @ 2015-06-27 13:11  jiu~  阅读(1344)  评论(0编辑  收藏  举报