python异常 详解(续)

Python使用异常对象(Exception object)来表示代码中出现的错误,无论是语法错误还是缩进错误,都会引发异常情况。
如果这种异常没有被处理或者捕捉,程序就会回溯(Traceback),抛出异常信息,终止程序运行。
【1】python异常处理
当我们输入 s=raw_input('Please Enter:') 之后按回车, 然后,我们按下 Ctrl + D 
>>> s=raw_input('Please Enter:')
Please Enter:
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    s=raw_input('Please Enter:')
EOFError: EOF when reading a line

这时,我们获得了一个异常情况,EOF -----> end of file 。我们不希望程序崩溃,所以,我们要处理这个异常。

#!/usr/bin/env python/
#coding:utf-8
import sys
try:
    s=raw_input('Enter something:')#可能得到异常的语句
except EOFError,e: #锁定是哪种异常
    #下面是出现异常后的处理方法
    print 'EOFError:',e
    sys.exit()#退出
print s
第一次运行结果:
>>> 
Enter something:python #最后记得按Enter键
python
第二次运行结果:
>>> 
Enter something: #此处直接按ctrl+d
EOFError: EOF when reading a line

try:
    s = "hello"
    a=1/0#如果外层try子句中的代码引发异常,程序将直接跳转到外层try对应的except子句,而内部的try子句将不会被执行。 
    try:
        print s[0] + s[1]
        print s[0] - s[1] #TypeError
    except TypeError,e:
        print 'TypeError:',e
except: #可以捕获所有异常
        print "产生异常"
运行结果:
产生异常

try:
    s = "hello"
    #a=1/0#如果外层try子句中的代码引发异常,程序将直接跳转到外层try对应的except子句,而内部的try子句将不会被执行。 
    try:
        print s[0] + s[1]
        print s[0] - s[1] #TypeError
    except TypeError,e:
        print 'TypeError:',e
except: #可以捕获所有异常
        print "产生异常"
运行结果:
he
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Python是面向对象语言,所以程序抛出的异常也是类。

try:
    a=1/0
except ZeroDivisionError,e:#e是一个异常类的实例,包含了来自异常代码的诊断信息。
    print 'ZeroDivisionError:',e
    print type(e)
    print e.__class__
    print e.__class__.__doc__
    print e.__class__.__name__
运行结果:
ZeroDivisionError: integer division or modulo by zero
<type 'exceptions.ZeroDivisionError'>
<type 'exceptions.ZeroDivisionError'>
Second argument to a division or modulo operation was zero.
ZeroDivisionError
【2】使用raise抛出异常
在程序中主动抛出异常,该怎么办呢?可以使用raise语句,其基本语法如下:
raise [SomeException [, args [,traceback]] 
第一个参数,SomeException必须是一个异常类,或异常类的实例
第二个参数是传递给SomeException的参数,必须是一个元组。这个参数用来传递关于这个异常的有用信息。
第三个参数traceback很少用,主要是用来提供一个跟踪记录对象(traceback)
下面举几个例子:

>>> raise NameError
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    raise NameError
NameError
>>> raise NameError() #异常类的实例  
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    raise NameError()
NameError
>>> raise NameError,('There is a name error','in abc.txt')
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    raise NameError,('There is a name error','in abc.txt')
NameError: ('There is a name error', 'in abc.txt')
>>> raise NameError('There is a name error','in abc.txt')#注意跟上面一个例子的区别 
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    raise NameError('There is a name error','in abc.txt')
NameError: ('There is a name error', 'in abc.txt')
>>> raise NameError,NameError('There is a name error','in abc.txt')#注意跟上面一个例子的区别 
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    raise NameError,NameError('There is a name error','in abc.txt')
NameError: ('There is a name error', 'in abc.txt')
我们最常用的还是,只传入第一个参数用来指出异常类型,最多再传入一个元组,用来给出说明信息。


当程序出现错误,python会自动引发异常,也可以通过raise显式地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。

try:
    s=None
    if s is None:
        print 's是空对象!'
        raise NameError,'空对象没有长度' #如果引发NameError异常,后面的代码将不能执行  
    print 'len(s)=',len(s)
except NameError,e:
    print e
except TypeError,e:
    print e
else:
    print 'no error!'
finally:
    print 'this is the last step!'
运行结果:
s是空对象!
空对象没有长度
this is the last step!

try:
    s='abc'
    if s is None:
        print 's是空对象!'
        raise NameError,'空对象没有长度' #如果引发NameError异常,后面的代码将不能执行  
    print 'len(s)=',len(s)
except NameError,e:
    print e
except TypeError,e:
    print e
else:
    print 'no error!'
finally:
    print 'this is the last step!'
运行结果:
len(s)= 3
no error!
this is the last step!

try:
    s=34
    if s is None:
        print 's是空对象!'
        raise NameError,'空对象没有长度' #如果引发NameError异常,后面的代码将不能执行  
    print 'len(s)=',len(s) #TypeError
except NameError,e:
    print e
except TypeError,e:
    print e
else:
    print 'no error!'
finally:
    print 'this is the last step!'
运行结果:
len(s)= object of type 'int' has no len()
this is the last step!

【3】python自定义异常
python允许程序员自定义异常,用于描述python中没有涉及的异常情况,自定义异常必须直接或间接继承Exception类,
自定义异常按照命名规范以"Error"结尾,显式地告诉程序员这是异常。自定义异常使用raise语句引发,而且只能通过人工方式触发。

class MyError(Exception):
    def __init__(self,value):
        print 'MyError.__init__() is called!'
        self.value=value
    def __str__(self):
        return repr(self.value)

raise MyError(88)
#raise MyError('error!')
运行结果:
MyError.__init__() is called!
Traceback (most recent call last):
  File "E:\workspace\python04\oop\kk.py", line 11, in <module>
    raise MyError(88)
__main__.MyError: 88

class MyError(Exception):
    def __init__(self,value):
        print 'MyError.__init__() is called!'
        self.value=value
    def __str__(self):
        return repr(self.value)

#raise MyError(88)
raise MyError('error!')
运行结果
MyError.__init__() is called!
Traceback (most recent call last):
  File "E:\workspace\python04\oop\kk.py", line 12, in <module>
    raise MyError('error!')
__main__.MyError: 'error!'

from __future__ import division
class DivisionException(Exception):
    def __init__(self, x, y):
        print 'DivisionException.__init__() is called!'
        #Exception.__init__ (self, x, y) #调用基类的__init__进行初始化
        self.x = x
        self.y = y

if __name__ == "__main__":
    try:
        x = 6
        y = 2
        if x%y>0:
            print x/y
            raise DivisionException(x,y)
    except DivisionException,div:   #div 表示DivisionException类的实例
        print "DivisionExcetion: x/y = %.2f" % (div.x/div.y)
    else:
        print 'no error!'
    finally:
        print 'this is the last step!'
运行结果:
no error!
this is the last step!

from __future__ import division
class DivisionException(Exception):
    def __init__(self, x, y):
        print 'DivisionException.__init__() is called!'
        #Exception.__init__ (self, x, y) #调用基类的__init__进行初始化
        self.x = x
        self.y = y

if __name__ == "__main__":
    try:
        x = 7
        y = 2
        if x%y>0:
            print x/y
            raise DivisionException(x,y)
    except DivisionException,div:   #div 表示DivisionException类的实例
        print "DivisionExcetion: x/y = %.2f" % (div.x/div.y)
    else:
        print 'no error!'
    finally:
        print 'this is the last step!'
运行结果:
3.5
DivisionException.__init__() is called!
DivisionExcetion: x/y = 3.50
this is the last step!

#!/usr/bin/env python/
#coding:utf-8
#自定义异常类 
class MyInputException(Exception):
    def __init__(self,length,least):
        Exception.__init__(self)
        self.length=length
        self.least=least

try:
    s=raw_input('输入一个字符串:')
    if len(s)<5:
        raise MyInputException(len(s),5)
    print '字符串的长度符合要求!'
except EOFError:
    print '触发了EOF错误,按了Ctrl+D'
except MyInputException,e:
    print '输入的字符串长度为%d,期望的长度至少是%d' % (e.length,e.least)
except Exception:
    print 'unknown error!'
else:
    print 'no error!'
finally:
    print 'this is the last step!'
第一次运行结果:
>>> 
输入一个字符串:abc
输入的字符串长度为3,期望的长度至少是5
this is the last step!
第二次运行结果:
>>> 
输入一个字符串:12345
字符串的长度符合要求!
no error!
this is the last step!
第三次运行结果:
>>> 
输入一个字符串:#此处直接按Ctrl+D
触发了EOF错误,按了Ctrl+D
this is the last step!

【4】采用traceback模块查看异常

import traceback
try:
    a=1/0
except: #可以捕获所有异常
    print 'there is a error!'
    traceback.print_exc()


运行结果:
there is a error!
Traceback (most recent call last):
  File "E:\workspace\python04\oop\kk.py", line 6, in <module>
    a=1/0
ZeroDivisionError: integer division or modulo by zero
我们也可以把异常保存到一个日志文件中,来分析这些异常,请看下面的方法:

import traceback
try:
    a=1/0
except: #若except子句不跟任何异常和异常参数,则可以捕获任何异常。
    f=open('C:\Users\91135\Desktop\errorLog.txt','a') 
    traceback.print_exc(file=f) #把traceback.print_exc()打印在屏幕上的信息保存到一个文本文件中。
    f.flush()
    f.close()
【5】python抛出的常见异常,示例如下:
>>> print var
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    print var
NameError: name 'var' is not defined
>>> var=1/0
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    var=1/0
ZeroDivisionError: integer division or modulo by zero
>>> int float 4.5
SyntaxError: invalid syntax
>>> L=[2,3,4]
>>> L[3]
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    L[3]
IndexError: list index out of range
>>> d={'name':'python','age':23}
>>> d['id']
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    d['id']
KeyError: 'id'
>>> f=open('abc.txt','r')
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    f=open('abc.txt','r')
IOError: [Errno 2] No such file or directory: 'abc.txt'
>>> class A():
        def __init__(self,x,y):
            self.x=x
            self.y=y

>>> a=A(3,4)
>>> print a.z
Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    print a.z
AttributeError: A instance has no attribute 'z'
>>> int('abc')
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    int('abc')
ValueError: invalid literal for int() with base 10: 'abc'
>>> s='23'
>>> i=8
>>> print s+i
Traceback (most recent call last):
  File "<pyshell#45>", line 1, in <module>
    print s+i
TypeError: cannot concatenate 'str' and 'int' objects
>>> assert 1!=1,'error!'
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    assert 1!=1,'error!'
AssertionError: error!
>>> class A(object):
        def __init__(self):
            pass
        def func(self):
            raise NotImplementedError

>>> a=A()
>>> a.func()
Traceback (most recent call last):
  File "<pyshell#54>", line 1, in <module>
    a.func()
  File "<pyshell#52>", line 5, in func
    raise NotImplementedError
NotImplementedError
定义一个类,一个接口方法func,如果直接调用func,则抛NotImplementedError异常,这样做的目的通常是用来模拟接口。
LookupError:键、值不存在引发的异常。LookupError异常是IndexError、KeyError的基类。
如果我们不确定数据类型是字典还是列表时,可以用LookupError捕获此异常,如下:
try:
    d={'age':23,'name':'python'}
    print d['id']
except LookupError,e:
    print 'LookupError:',e


try:
    l=[2,3,2]
    print l[3]
except LookupError,e:
    print 'LookupError:',e
运行结果:
LookupError: 'id'
LookupError: list index out of range

StandardError 标准异常。
除StopIteration, GeneratorExit, KeyboardInterrupt 和SystemExit外,其他异常都是StandarError的子类。
【6】断言(assert)
assert expression[,reason]
其中assert是断言的关键字。执行该语句的时候,先判断表达式expression,如果表达式为真,则什么都不做;
如果表达式为假,则抛出AssertionErro异常,而且我们传进去的字符串会作为异常类的实例的具体信息存在。
reason跟我们之前谈到的异常类的实例一样。

assert len('python')==len('hello!')#表达式为真,则什么都不做
assert 1==1 #表达式为真,则什么都不做
assert 1==3,'1 is not equal to 3' #表达式为假,则抛出异常

assert异常也可以被try块捕获,如下:

try:
    assert 1==2,'1 is not equal to 2'
except AssertionError,e:
    print e
    print type(e),e.__class__
    print e.__class__.__name__
    print '%s:%s' % (e.__class__.__name__,e) 
运行结果:
1 is not equal to 2
<type 'exceptions.AssertionError'> <type 'exceptions.AssertionError'>
AssertionError
AssertionError:1 is not equal to 2

【7】异常和sys模块
另一种获取异常信息的途径是通过sys模块中的exc_info()函数。该函数回返回一个三元组:(异常类,异常类的实例,跟踪记录对象)。

try:
    a=1/0
except:
    import sys
    tuple=sys.exc_info()
    print tuple
    for i in tuple:
        print i
运行结果:
(<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division or modulo by zero',), <traceback object at 0x02686558>)
<type 'exceptions.ZeroDivisionError'> #异常类
integer division or modulo by zero  #异常类的实例
<traceback object at 0x02686558>    #跟踪记录对象

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值