python 异常处理

来源:互联网 发布:域名代表什么 编辑:程序博客网 时间:2024/05/20 04:49

目录(?)[+]

目录

  • 目录
  • 异常
  • 异常类型
  • 异常处理
    • 触发异常raise
    • 传递异常
    • assert语句触发异常
    • 捕获异常tryexceptelse
    • 捕捉多个异常
    • tryfinally语句
    • 自定义异常
    • withas触发异常自动关闭资源
    • as获取异常信息
    • 异常参数
    • traceback追踪异常
    • sysexc_info获取异常信息
  • 最后

异常

异常即非正常状态,在Python中使用异常对象来表示异常。若程序在编译或运行过程中发生错误,程序的执行过程就会发生改变,抛出异常对象,程序流进入异常处理。如果异常对象没有被处理或捕捉,程序就会执行回溯(Traceback)来终止程序。

异常类型

通用异常类型表

异常描述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尚未实现的方法SyntaxErrorPython 语法错误IndentationError缩进错误TabErrorTab 和空格混用SystemError一般的解释器系统错误TypeError对类型无效的操作ValueError传入无效的参数UnicodeErrorUnicode 相关的错误UnicodeDecodeErrorUnicode 解码时的错误UnicodeEncodeErrorUnicode 编码时错误UnicodeTranslateErrorUnicode 转换时错误Warning警告的基类DeprecationWarning关于被弃用的特征的警告FutureWarning关于构造将来语义会有改变的警告OverflowWarning旧的关于自动提升为长整型(long)的警告PendingDeprecationWarning关于特性将会被废弃的警告RuntimeWarning可疑的运行时行为(runtime behavior)的警告SyntaxWarning可疑的语法的警告UserWarning用户代码生成的警告

Exception类:是通用异常基类下列异常类均继承于Exception类,python解析器会自动将通用异常类型名称放在内建命名空间中,所以当使用通用异常类型时,不需要import exceptions模块。

异常处理

触发异常raise

raise关键字:手动抛出一个通用的异常类型(Exception),类似Java中的throw语句。raise关键字后跟异常的名称,异常名称能够标识出异常类的对象。执行raise语句时,python会创建指定异常类的对象,还能够指定对异常对象进行初始化的参数,参数也可以为由若干参数组成的元组。 
注意:一旦执行raise语句,程序就会被终止。 
格式raise [exceptionType[,argument][,traceback]]

def testRaise(number):    if number < 1:        raise ValueError('Invalid value') #或者 raise ValueError,'Invalid value'testRaise(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

traceback:这个参数用于追踪异常对象,一般很少使用。 
这样就可以触发一个异常,并且接收异常信息。

传递异常

当你捕获到异常之后又希望再次的触发异常只需要使用不带任何参数的raise关键字。

!/usr/bin/env pythonimport ostry:    openFile = open('notExistsFile.txt','r')    fileContent = openFile.readlines()except IOError:    print 'File not Exists'    if not os.path.exists('notExistsFile.txt'):        raiseexcept:    print 'process exception'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

异常会在捕获之后再次触发同一个异常。

assert语句触发异常

assert语句根据后面的表达式的真假来控制程序流。若为True,则往下执行。若为False,则中断程序并调用默认的异常处理器,同时输出指定的提示信息。 
格式:

assert expression,'information'
  • 1
  • 1

Example:

#!/usr/bin/env pythondef testAssert(x):    assert x < 1,'Invalid value'testAssert(1)print 'Valid value'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

output:

AssertionError: Invaild value
  • 1
  • 1

捕获异常try..except..else

注意:except子句的数量没有限制,但使用多个except子句捕获异常时,如果异常类之间具有继承关系,则子类应该写在前面,否则父类将会直接截获子类异常。放在后面的子类异常也就不会执行。 
格式:

try:    可能触发异常的语句块except [exceptionType]:    捕获可能触发的异常[可以指定处理的异常类型]except [exceptionType][,date]:    捕获异常并获取附加数据except:    没有指定异常类型,捕获任意异常else:    没有触发异常时,执行的语句块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

try的工作原理: 
执行一个try语句时,python解析器会在当前程序流的上下文中作标记,当出现异常后,程序流能够根据上下文的标记回到标记位,从而避免终止程序。 
1. 如果try语句执行时发生异常,程序流跳回标记位,并向下匹配执行第一个与该异常匹配的except子句,异常处理完后,程序流就通过整个try语句(除非在处理异常时又引发新的异常)。 
2. 如果没有找到与异常匹配的except子句(也可以不指定异常类型或指定同样异常类型Exception,来捕获所有异常),异常被递交到上层的try(若有try嵌套时),甚至会逐层向上提交异常给程序(逐层上升直到能找到匹配的except子句。实在没有找到时,将结束程序,并打印缺省的错误信息)。 
3. 如果在try子句执行时没有发生异常,python将执行else语句后的语句(可选),然后控制流通过整个try语句。

#!/usr/bin/env pythontry:    openFile = open('notExistsFile.txt','r')    fileContent = openFile.readlines()except IOError:       print 'File not Exists'        #执行except:    print 'process exception'      #不执行else:    print 'Reading the file'       #不执行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

output:

In [157]: %run testError.pyFile not Exists
  • 1
  • 2
  • 1
  • 2

嵌套try

#!/usr/bin/env pythontry:    try:        openFile = open('notExistsFile.txt','r')        fileContent = openFile.readlines()    except IOError:        print 'File not Exists'      #执行except:    print 'process exception'        #不执行 else:     print 'Reading the file'         #执行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Output:

In [159]: %run testError.pyFile not ExistsReading the file
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

捕捉多个异常

方法一:指定一个通用异常,可以捕获多个不同的包含在Exception类中的异常类。

try:    语句块except Exception:    语句块
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

方法二:在一个except子句后将多个异常作为元组元素列出。

try:    语句块except (IOError,ValueError):     语句块
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

方法三:except子句后不带任何异常名称,捕获所有异常

try:    语句块except:     语句块
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

try..finally语句

无论try语句块中是否触发异常,都会执行finally子句中的语句块,因此一般用于关闭文件或关闭因系统错误而无法正常释放的资源。比如文件关闭,释放锁,把数据库连接返还给连接池等。

import osdef write_test(fileName,content_iterable):    try:        pwd = open(fileName,'w')        for key,value in content_iterable.items():            pwd.write(key+'\t'+value+'\n')  #传入String类型参数同时加入换行符    finally:        pwd.close()if __name__ == '__main__':    fileName = '/usr/local/src/pyScript/fileOperation.txt'    dic = {'name':'Jmilk','age':'23','city':'BJ'}    if os.path.exists(fileName):        write_test(fileName,dic)    else:print 'File not exist!'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

注意:try..finally与try..except 是可以同时使用的。

In [3]: try:   ...:     raise   ...: except Exception:   ...:     print 'error'   ...:     raise   ...: finally:   ...:     print 'success'   ...:errorsuccess---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-3-530db52949e7> in <module>()      1 try:----> 2     raise      3 except Exception:      4     print 'error'      5     raiseTypeError: exceptions must be old-style classes or derived from BaseException, not NoneType
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

NOTE:try…finally 的意义在于,就是我们在 try 代码块中执行了 return 语句,但是仍然会继续执行在 finally 中的代码块,所以我们一般用作处理资源的释放。

自定义异常

通过(直接或简介)继承Exception类来创建一个自定义异常类,自定义的异常类只能通过raise关键字来手动触发。

class testError(Exception):    #直接集成Exception类    def __init__(self,arg):        self.args = argtry:    raise testError('Just test')except testError,info:    print info.args
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

output:

In [52]: %run test.py('J', 'u', 's', 't', ' ', 't', 'e', 's', 't')
  • 1
  • 2
  • 1
  • 2

with..as触发异常自动关闭资源

在使用类文件的流对象时,都需要单独的调用close()来关闭资源。with..as语句能够实现在with语句块执行完后,自动的关闭文件。如果with语句块中触发异常,会调用默认的异常处理器处理,而且文件仍然能够正常关闭。

#!/usr/bin/env pythonimport osdef testWith(fileName):    try:        with open(fileName,'r+') as pwd:            pwd.readlines()            print 2/0    except Exception:            print 'File closed:',pwd.closed  #判断文件是否关闭if __name__ == '__main__':    if os.path.exists('/usr/local/src/pyScript/fileOperation.txt'):        testWith('/usr/local/src/pyScript/fileOperation.txt')        print 'continue'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

output:

In [17]: %run test.pyFile closed: True    #没有call close()函数,文件仍然自动关闭。continue
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

as获取异常信息

每个异常都会有一定的描述信息,可以通过as关键字来获取。但是这种异常信息并不适合一般用户阅读,所以会使用自定义的异常信息。但是仍然会将原有的异常信息保留起来,用于后期的异常分析。

#!/usr/bin/env pythontry:    try:        openFile = open('notExistsFile.txt','r')        fileContent = openFile.readlines()    except (IOError,ValueError) as info:  #或者except (IOError,ValueError),info:         print infoexcept:    print 'process exception'else:    print 'Reading the file'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

output:

In [164]: %run testError.py[Errno 2] No such file or directory: 'notExistsFile.txt'Reading the file
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

异常参数

也可以使用异常参数作为输出的异常信息参数,来获取异常信息。并且异常参数中包含有异常信息、错误数字、错误位置等属性。

#!/usr/bin/env pythontry:    try:        openFile = open('notExistsFile.txt','r')        fileContent = openFile.readlines()    except (IOError,ValueError),info:        print dir(info)        print info.argsexcept:    print 'process exception'else:    print 'Reading the file'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

output:

In [44]: %run test.py['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', 'args', 'errno', 'filename', 'message', 'strerror'](2, 'No such file or directory')Reading the file
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

traceback追踪异常

使用traceback追踪异常的时候,需要import traceback模块。traceback模块可以有效的帮助查看异常的详细信息。 
注意:若希望获取异常的详细信息,却又不会终止程序的执行,可以在except子句中使用tarceback.print_exc()函数。 
tarceback.print_exc(): 
print_exc(limit=None, file=None) 
Shorthand for ‘print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, limit, file)’. 
(In fact, it uses sys.exc_info() to retrieve the same information in a thread-safe way.) 
输出sys.exc_type, sys.exc_value, sys.exc_traceback, limit, file等异常信息,实际上是以线程安全的方式去使用sys.exc_info()函数来获取相同的信息。

#!/usr/bin/env pythonimport tracebacktry:    openFile = open('notExistsFile.txt','r')    fileContent = openFile.readlines()except IOError as info:    print 'File not Exists'    print info    traceback.print_exc()    print 'continue'except:    print 'process exception'else:    print 'Reading the file'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

output:

In [38]: %run test.pyFile not Exists[Errno 2] No such file or directory: 'notExistsFile.txt'Traceback (most recent call last):  File "/usr/local/src/pyScript/test.py", line 5, in <module>    openFile = open('notExistsFile.txt','r')IOError: [Errno 2] No such file or directory: 'notExistsFile.txt'continue
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

异常信息的重定向:如果希望将异常的信息保存在一个指定的文件中,以供后期分析。可以使用下面的方法:

#!/usr/bin/env pythonimport tracebacktry:    with open('notExistsFile.txt','r') as openFile:        fileContent = openFile.readlines()except IOError:    with open('errorLog','w+') as errorInfo:        traceback.print_exc(file=errorInfo)    print 'continue'except:    print 'process exception'else:    print 'Reading the file'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

output:

In [61]: %run test.pycontinueIn [62]: cat errorLogTraceback (most recent call last):  File "/usr/local/src/pyScript/test.py", line 5, in <module>    with open('notExistsFile.txt','r') as openFile:IOError: [Errno 2] No such file or directory: 'notExistsFile.txt'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

sys.exc_info()获取异常信息

traceback.print_exc()函数实际上是call sys.exc_info()

import sys  try:      a=b      b=c  except:      info=sys.exc_info()      print info[0],":",info[1]  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

output:

In [65]: %run test.py<type 'exceptions.NameError'> : name 'b' is not defined
  • 1
  • 2
  • 1
  • 2

最后

异常处理用于处理程序错误之外,还有许多应用的地方。如关闭资源、平台兼容、模块导入等。这些使用都是基于对异常处理的实现和机制的理解上,以后我们再一起学习。