zoukankan      html  css  js  c++  java
  • 《python学习手册》第34章 异常对象

    基于字符串的异常

    python在2.6之前可以使用字符串来定义异常,并且是通过对象标识符来匹配的(即通过is 而不是==)

    myexc = "My excetion string"
    try:
        raise myexc
    except myexc:
        print('caught')

    基于类的异常

    字符串定义的异常非常简单,但是并不容易维护。使用类定义的异常通过超类关系进行匹配,只要except列举出来的异常的类或者任何超类名,引发的异常都会匹配到。此外,类的异常还支持异常状态信息,可以让异常参与继承层次。

    类异常的例子

    class General(Exception):pass
    class Special1(General):pass
    class Special2(General):pass
    def raise0(): raise General()
    def raise1(): raise Special1()
    def raise2(): raise Special2() 
    
    for fun in (raise0,raise1,raise2):
        try:
            fun()
        except General:
            import sys
            print('caught',sys.exc_info()[0])

    运行的结果如下

    caught <class '__main__.General'>
    caught <class '__main__.Special1'>
    caught <class '__main__.Special2'>

    将excep的部分化为下面的内容,结果一样,sys.exc_info将在下一章讲到。

        except General as x:
            print('caught:',x.__class__)

    类异常的另一个例子

    假如我们维护了一个mathlib.py的库,原本定义了两个异常Divzero和Oflow,

    class Divzero(Exception): pass
    class Oflow(Exception): pass
    def func():
        raise Divzero()

    当别人使用我们的库的时候我们可以进行异常处理:

    import mathlib
    try:
        mathlib.func()
    except (mathlib.Divzero,mathlib.Oflow):
        '''do what you want to do '''

    但是,当我们维护我们的库的时候新加入一个异常Uflow的时候,别人必须修改他们的代码,这样在大型程序当中非常的不好。所以我们尝试把我们库中的代码写成下面的形式:

    class NumErr(Exception):pass
    class Divzero(NumErr): pass
    class Oflow(NumErr): pass
    '''其余的异常'''
    def func():
        raise Divzero()

    别人引用的时候只需要写成下面的形式即可:

    import mathlib
    try:
        mathlib.func()
    except mathlib.NumErr:
        '''do what you want to do '''

    无论我们增加多少个异常的类,别人的代码都不需要进行修改。

    内置Exception类

    -BaseException类:异常的顶级根类,不可以被用户定义的类直接继承(应当使用Exception)。它提供了子类所继承的默认的打印和状态保持行为。

    -Exception类:与应用相关的异常的顶层根超类,是BaseExcption的一个直接子类,并且是所有其他内置异常的超类,除了系统退出事件类以外(SystemExit、KeyboardInterrupt和GeneratorExit)。

    In [2]: Exception.__bases__
    Out[2]: (BaseException,)
    In [3]: SystemExit.__bases__
    Out[3]: (BaseException,)

    -ArithmeticeError 所有数值错误的超类

    In [4]: ArithmeticError.__bases__
    Out[4]: (Exception,)

    -OverflowError 识别特定的数值错误的子类

    In [5]: OverflowError.__bases__
    Out[5]: (ArithmeticError,)

    从上面的代码可以看出,python中的异常总是这样的进行继承的

    默认打印和状态

    python内置异常提供默认的打印方法:传递给这些类的任何构造函数参数都会保存在实例的args元祖属性中,并且当打印该实例的时候自动显示。这就说明了为什么传递给内置异常类的参数会出现在出错消息中。

    输入:

    raise IndexError

    输出:

    Traceback (most recent call last):
      File "D:applicationeclipseworkspaceyichangc3	6.py", line 1, in <module>
        raise IndexError
    IndexError

    输入:

    raise IndexError('nihao')

    输出:

    Traceback (most recent call last):
      File "D:applicationeclipseworkspaceyichangc3	6.py", line 1, in <module>
        raise IndexError('nihao')
    IndexError: nihao

    输入:

    i = IndexError('nihao')
    print(i.args)

    输出:

    ('nihao',)

    同样,我们自己定义的类也是如此,因为他们继承了内置超类中存在的构造很熟和显示方法

    输入:

    class MyErr(Exception):pass
    
    try:
        raise MyErr('nihao')
    except MyErr as x:
        print(x,x.args)

    输出:

    nihao ('nihao',)

    输入:

    class MyErr(Exception):pass
    
    try:
        raise MyErr('nihao','wohao','dajiahao')
    except MyErr as x:
        print(x,x.args)

    输出:

    ('nihao', 'wohao', 'dajiahao') ('nihao', 'wohao', 'dajiahao')

    为什么输出x和x.args是一样的?因为,这是由于__str__来决定的,直接输出了str(args)。

    定制我们自己的打印显示:

    其实,主要是修改我们定制的类中的__str__和__repr__方法,而__str__又是主要的。

    下面我们为我们自己定义的类当中重定义__str__方法:

    class MyErr(Exception):
        def __str__(self):
            return 'this is MYErr Exception'
    
    try:
        raise MyErr('nihao','wohao','dajiahao')
    except MyErr as x:
        print(x)

    输出: this is MYErr Exception 

    改造构造方法

    class FormatError(Exception):
        def __init__(self,line,file):
            self.line = line
            self.file = file
    
    try:
        raise FormatError(2,'nihao')
    except FormatError as x:
        print(x.line,x.file)
        print(x.args[0],x.args[1])

    通过改造构造方法,可以体统更多的细节,但是args还是可以使用的,输出结果如下:

    2 nihao
    2 nihao

    定义一些方法,在处理器内部执行

    class FormatError(Exception):
        logfile = r'log.txt'
        def __init__(self,line,file):
            self.line = line
            self.file = file
        def logger(self):
            log = open(self.logfile,'a')
            print('error at line:',self.line,'file:',self.file,file=log)
    
    try:
        raise FormatError(11,'t7.txt')
    except FormatError as x:
        x.logger()

    该异常定义了出错的时候存入特定文件夹的功能,当捕获异常的时候,执行logger方法

    执行后在log.txt中有如下语句: error at line: 11 file: t7.txt 


    总结:这一章我们其实是明确了,异常主要是通过类来实现的,在try语句中,捕捉其超类就会捕捉这个类,以及类树中超类下的所有子类。

  • 相关阅读:
    实用的设计模式【一】---类设计法则
    vimium 使用心得
    记一次给部门做分享的心得
    centos7安装docker和docker compose【转】
    docker 部署 jenkins
    centos删除docker0虚拟网卡
    CentOS7查看和关闭防火墙
    .Net Core Autofac实现依赖注入
    【转】Docker基础
    【转】使用Docker+Jenkins自动构建部署
  • 原文地址:https://www.cnblogs.com/jiaxin359/p/7326246.html
Copyright © 2011-2022 走看看