您的位置:首页 > 编程语言 > Python开发

python基础之异常

2016-01-27 20:06 711 查看
python用异常对象(exception object)来表示异常情况。遇到错误后,会引发异常。如果异常对象并未被处理或者捕获,程序就会用所谓的回溯(traceback,一种错误信息)终止执行。

按照自己的方式出错

在学习处理异常之前,我们先看下如何引发异常以及创建自己的异常类型:

(1)raise语句

为了引发异常。可以使用一个类(Exception的子类)或者实力参数调用raise语句:

>>> raise Exception

Traceback (most recent call last):

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

Exception

>>> raise Exception('hello word')

Traceback (most recent call last):

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

Exception: hello world

第一个例子raise Exception引发了一个没有任何错误信息的异常。后一个例子添加了错误信息hello world.

内建的异常类有很多,这里我们看下一些最重要的异常类:

类名                                                                         描述

Exception                                                        所有异常的基类

AttributeError                                                  特性引用或者赋值失败时引发

IOError                                                            试图打开不存在文件时候引发

IndexError                                                       在使用序列中不存在的索引时引发

KeyError                                                          在使用映射中不存在的键时引发

NameError                                                       在找不到名字(变量)时引发

SyntaxError                                                      在代码为错误的形式时引发

TypeError                                                         在内建操作或者函数应用错误类型对象时引发

ValueError                                                        在内建操作或者函数应用正确类型的对象,但是该对象使用不适合的                                                                          值时引发

ZeroDivisionError                                             在除法或者模操作的第二个参数为0时引发

(2)自定义异常类

尽管内建的异常类已经包含了大部分的情况,但是有时候还是需要创建自己的类,那么如何创建自己的类呢,就像其它类一样,只是要确保是从Exception类继承:

class SomeCustomException(Exception): pass

如果你愿意,你也可以向你的异常类中添加方法。

捕捉异常

前面提到过,关于异常最有意思的地方就是可以处理它们(通常叫做诱捕或者捕捉异常)。这个功能可以使用try/except语句来实现。假设创建了一个让用户输入两个数,然后进行相加的程序:

x= input('Enter the first number:')

y= input('Enter the second number:')

print x/y

加入用户输入0作为第二个数:

Enter the first number:10

Enter the second number:0

Traceback (most recent call last):

  File "./test.py", line 5, in <module>

    print x/y

ZeroDivisionError: integer division or modulo by zero

为了捕捉异常并且做出一些错误处理(本例中只是输出一些友好信息),可以这样:

try:

    x= input('Enter the first number:')

    y= input('Enter the second number:')

    print x/y

except ZeroDivisionError:

    print 'hello word'

Enter the first number:1

Enter the second number:0

hello word

如果捕捉到了异常,但是又想重新引发它,那么可以使用不带参数的raise。

举个例子,看看这么做的用处:考虑下一个能“屏蔽”ZeroDivisionError的计算器类。如果这个行为被激活,那么计算机就会打印错误信息,而不是让异常传播。如果在与程序内部使用引发异常又会更好,所以”屏蔽“机制就可以关掉了,下面是这样一个类的代码:

class MuffledCalculator:

    muffled=False

    def calc(self,expr):

        try:

            return eval(expr)

        except ZeroDivisionError:

            if self.muffled:

                print 'Division by zero is illegal'

            else:

                raise

运行一下:

print calculator.calc('10/0')

Traceback (most recent call last):

  File "./test.py", line 14, in <module>

    print calculator.calc('10/0')

  File "./test.py", line 7, in calc

    return eval(expr)

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

ZeroDivisionError: integer division or modulo by zero

calculator.muffled=True

print calculator.calc('10/0')

Division by zero is illegal

None

不知一个except子句

如果在上面的那个程序里第二个数字输入非字符类型的值,那么
4000
就会产生第二个异常:

Enter the first number:1

Enter the second number:'a'

Traceback (most recent call last):

  File "./test.py", line 5, in <module>

    print x/y

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

因为except子句值寻找ZeroDivisionError异常,这次的错误就溜过了检查并导致程序终止,为了捕捉这个异常,我们可以在try/except语句后面加上里一个except子句:

try:

    x=input('Enter the first number:')

    y=input('Enter the second number:')

    print x/y

except ZeroDivisionError:

    print 'a'

except TypeError:

    print 'b'

用一个块捕捉两个异常

如果需要用一个块捕捉多个类型异常,那么可以将它们作为元组列出,像下面这样:

try:

    x=input('Enter the first number:')

    y=input('Enter the second number:')

    print x/y

except (ZeroDivisionError,TypeError):

    print 'hello world'

[root@localhost python]# ./test.py

Enter the first number:1

Enter the second number:'a'

hello world

捕捉对象

如果希望在excep子句中访问异常对象本身,可以使用两个参数(注意,就算捕捉到多个异常,也只需向except子句提供一个参数——一个元组),比如想让程序继续运行,但是又因为某种原因想记录下错误(比如只是打印给用户看),这个功能就很有用:

try:

    x=input('Enter the first number:')

    y=input('Enter the second number:')

    print x/y

except (ZeroDivisionError,TypeError),a:

    print a

[root@localhost python]# ./test.py

Enter the first number:1

Enter the second number:'a'

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

真正的全捕获

就算程序可以处理好几种类型的异常,但是有些异常还是会从眼皮地下溜走,但是如果想用一段代码捕获所有的异常,就可以在except子句中忽略所有的异常类:

try:

    x=input('Enter the first number:')

    y=input('Enter the second number:')

    print x/y

except:

    print 'hello world'

警告:这样的全捕获是危险的,因为它会隐藏程序员未想到并且未做好准备处理的错误。这时还是使用except Exception,e这样好点

万事大吉

可以像条件和循环语句那样,给try/except语句加个else子句:

while True:

    try:

        x=input('Enter the first number:')

        y=input('Enter the second number:')

        print x/y

    except Exception,e:

        print e

    else:

        break

[root@localhost python]# ./test.py

Enter the first number:1

Enter the second number:0

integer division or modulo by zero

Enter the first number:''^[[Da

invalid syntax (<string>, line 1)

Enter the first number:'a'

Enter the second number:'a'

unsupported operand type(s) for /: 'str' and 'str'

Enter the first number:10

Enter the second number:2

5

最后.......

最后是finally子句,它可以用来在可能的异常后进行清理,它和try子句联合使用:

x=None

try:

    x=1/0

finally:

    print 'clean up'

    del x

[root@localhost python]# ./test.py

clean up

Traceback (most recent call last):

  File "./test.py", line 5, in <module>

    x=1/0

ZeroDivisionError: integer division or modulo by zero

finally子句肯定会被执行,不管try子句中是否发生异常的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python