python基础之异常

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子句

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

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子句中是否发生异常的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值