1异常的由来

         说到异常,通常首先要讲的是错误,在写程序的过程中,会出现各种各样的错误,可能是语法错误,也可能是逻辑错误,那么当程序再运行的过程中,如果是语法错误,那么必须修正之后才能进行运行,如果是逻辑错误,那么可能是不合法的输入,也有可能是不完整的输入,或者无法输出,运行到相关的范围就会出现了错误。

         python检测到一个错误之后,那么就会出现一个异常。

         python程序的运行,先写出源代码文件以.py结尾的文件,然后由python解释器进行解释生成python字节码文件,通常以.pyc结尾,然后再将整个字节码文件到处理器上进行运行,当有一步出现错误的时候,就会产生一个异常。

         异常:程序出现了错误而在正常控制流以外采取的行为

         通常异常会分为两个阶段:一个阶段是引起异常的错误,另外一个阶段是检测处理阶段。


2异常的触发形式

         异常可以是python解释器触发,也可以是手动触发。

         python解释器遇到错误的时候,那么就会抛出一个异常,如果这个异常没有被捕获,那么就会向上级程序抛出,一直到顶层程序,最后抛出异常,程序执行流程被中断,也就是当异常没有被捕获处理的时候,那么就会导致程序中断运行。

         当手动触发的时候,可以使用raise语句来手动触发异常。

         在捕获处理异常的时候,一般只能预见到部分异常,从而进行处理,在处理异常的时候,应该返回相关的错误信息,或者写入到相关的日志文件中,而不应该没有任何输出。

 

3 python中常见的异常

         python中常见的异常如下所示:

>>> foo  访问一个未定义的变量,产生NameErrot异常

Traceback (most recent call last):

  File"<stdin>", line 1, in <module>

NameError: name 'foo' is not defined

>>> 3 +"a" 类型异常,不同的类型进行加操作,python是弱类型语言,只有在赋值之后才会有相关的类型

Traceback (most recent call last):

  File"<stdin>", line 1, in <module>

TypeError: unsupported operand type(s) for +: 'int'and 'str'

>>> for语法异常

  File"<stdin>", line 1

    for

      ^

SyntaxError: invalid syntax

>>> alist = [1];alist[3]索引异常

Traceback (most recent call last):

  File"<stdin>", line 1, in <module>

IndexError: list index out of range

>>> 键盘异常

KeyboardInterrupt

         当在程序中出现异常之后,会导致程序的中断运行,如下所示:

[root@python tmp]# cat kel.py 模块文件内容如下,程序开始打印start,程序结束打印end

#!/usr/bin/env python

 

print "start"

3 + "a"

print "end"

[root@python tmp]# python kel.py 打印了start,但是中间出现了异常,从而打破了正常的执行流程,异常发生后,后面的语句不会再执行,运行的程序中断

start

Traceback (most recent call last):

  File"kel.py", line 4, in <module>

    3 +"a" 抛出了异常,异常后面的代码未执行

TypeError: unsupported operand type(s) for +: 'int'and 'str'

 

4检测和处理异常

         在检测异常的时候,使用try关键字,在处理异常的时候,使用except语句,在其中,可以有多个except语句进行捕获不同类型的异常,当程序正常执行的时候,可以使用else语句来执行其他的流程,当出现异常或者程序都正常的时候,可以使用finally语句来进行一些程序的清理工作,例如将打开的文件进行关闭,

         每个except可以处理一个异常,如下:

[root@python tmp]# cat commonutils.py 每个except捕获一个异常,并且返回异常的详细信息

#!/usr/bin/env python

 

def safe_float(obj):

    try:

        retval= float(obj)

    except ValueError,e:

        retval= str(e)

    except TypeError,e:

        retval= str(e)

    returnretval

if __name__ == "__main__":

    printsafe_float("2b")

    printsafe_float("2")

    printsafe_float([1,2,3])

[root@python tmp]# python commonutils.py 当异常抛出的时候,异常被捕获并处理,从而程序会继续运行

invalid literal for float(): 2b

2.0

float() argument must be a string or a number

        

         一个except也可以处理多个异常,不过这些异常必须是元祖的形式存在,如下:

[root@python tmp]# cat commonutils.py 一个except处理多个异常,并返回错误信息

#!/usr/bin/env python

 

def safe_float(obj):

    try:

        retval= float(obj)

    except (TypeError,ValueError),e:

        retval= str(e)

    returnretval

if __name__ == "__main__":

    printsafe_float("2b")

    printsafe_float("2")

    printsafe_float([1,2,3])

[root@python tmp]# python commonutils.py

invalid literal for float(): 2b

2.0

float() argument must be a string or a number当异常抛出的时候,异常被捕获并处理,从而程序会继续运行

        

         使用else分支来表示正常执行的逻辑,如下所示:

[root@python tmp]# cat commonutils.py 当文件被正常打开之后,可以在else中做一些正常流程的事,如果触发了异常,那么else代码块中的语句不会被执行

#!/usr/bin/env python

 

try:

    f =open('/tmp/kel.txt')

except IOError,e:

    printtype(e)

    printstr(e)

else:

    f.close()

    print"file is closed"

[root@python tmp]# python commonutils.py

file is closed

         finally子句表示无论异常是否发生,都是会执行,如下所示:

[root@python tmp]# cat commonutils.py

#!/usr/bin/env python

 

try:监控异常

    f =open('/tmp/kel.txt')

except IOError,e捕获异常:

    printtype(e)

    printstr(e)

else:正常执行时候执行

    print"file is open"

finally:无论是否触发异常都会执行

    print"always execute"

    f.close()

[root@python tmp]# python commonutils.py

file is open

always execute

 

5所有的异常都是类

         所有的异常都是一个一个对象,如下所示:

[root@python tmp]# cat commonutils.py 查看异常的类型

#!/usr/bin/env python

 

try:

    f =open('/tmp/somefile.txt')

except IOError,e:

    printtype(e)

    printstr(e)

[root@python tmp]# python commonutils.py

<type 'exceptions.IOError'>

[Errno 2] No such file or directory:'/tmp/somefile.txt

         在捕获异常的时候,这个异常的原因是可写可不写的,当写的时候,这个e是一个异常类对象的实例,从上面的type可以看出,这是一个IOError异常的实例,从而每次返回错误的信息时候,需要转换成字符串的方式,也就是str(e),在转换的时候,实际上是调用e.__str__方法。

         异常对象的分类如下所示:

python异常_java

         从而需要捕获所有的异常的时候,可以直接在except中写Exception捕捉所有的内置异常,但是建议不要这么做。


6另外一种安全的打开文件的方式

         在打开文件的时候,可能需要各种判断,但是可以使用更加简单的方法,那就是with语句:

[root@python tmp]# python commonutils.py

Traceback (most recent call last):

  File"commonutils.py", line 5, in <module>

    some

NameError: name 'some' is notdefined

[root@python tmp]# cat commonutils.py

#!/usr/bin/env python

 

with open('/tmp/kel.txt') as f: 会自动执行代码的清理工作,也就是会将打开的文件进行关闭,取代了finally的工作,也会自动的抛出异常,但是依旧需要自行判断文件是否存在

    foreachline in f:

        some

        printeachline


7或许有用的例子

         在进行组织一些基础类库的时候,例如在打开文件的时候,总要判断文件是否存在,那么可以写一个基础的函数,只要直接进行调用,然后返回文件句柄即可,不用每次都来进行判断,如下所示:

[root@python tmp]# cat openfile.py 直接调用打开的文件函数,返回文件句柄,在主程序中,无需进行判断文件是否存在,是否会发生io错误

#!/usr/bin/env python

 

def openfile(filename,mode='r'):

    try:

        retval= open(filename,mode)

    exceptIOError,e:

        retval= None

    returnretval

 

if __name__ == "__main__":

    f =openfile('/tmp/kel.txt')

    if f:

        printlen(f.readlines())

    f =openfile('tmp/somefile')

    if f:

        printlen(f.readlines())

 

[root@python tmp]# python openfile.py

4