• Python 面向对象(其四)


    python中异常简述

    超人小明经历了太多生死,开始有点魔化了

        ---------------------------------------
                          魔化超人小明
        --------------------属性----------------
        --------------------方法----------------
            间歇性入魔:每隔一段时间,就会入魔一下
            突发性入魔:每次一入魔,小明都会干出很多奇怪而凶残的事情
            心魔洗练:小明在不停的自我压制魔念
    

    方法说明:

    • 间歇性入魔:
      • 因为都好多次了,所以小明甚至制定除了如何应对这种入魔的策略,可以不影响其他人事的情况下唤回自己
      • 对于异常情况可以额外预防,甚至可以优雅回退
    • 突发性入魔:
      • 因为不可预料性,所以一旦出现这种状况,只能让周围的人回避,并请出阿花阿芳阿草来进行唤回
      • 异常情况
    • 心魔洗练:
      • 小明一直在自我调节,压制魔念,让自己更清明
      • 代码中的容错,一旦写的不好就完犊子了

    如上,代码表现为:

      1 #! coding:utf-8
      2 import random
      3 
      4 #自定义异常表现
      5 class BlackInsideError(Exception):
      6     '''
      7         通常仅需要重写这两个方法就好
      8     '''
      9 
     10     def __init__(self, value):
     11         '''
     12             可以在异常类中进行各种预设的处理情况
     13         '''
     14         self.value = value
     15         BlackSuperManXiaoMing.isNormal = False
     16 
     17     def __str__(self):
     18         '''
     19             print Exception时使用。所有支持print(obj)的对象都有__str__方法
     20         '''
     21         return "{},每次入魔小明都会干出奇怪而可怕的事情".format(self.value)
     22 
     23 
     24 class BlackSuperManXiaoMing(SuperXiaoMing):
     25 
     26     isNormal = True
     27 
     28     def __init__(self,relationship):
     29         super(BlackSuperManXiaoMing, self).__init__(relationship)
     30 
     31     def call_me_back(self):
     32         BlackSuperManXiaoMing.isNormal = True
     33         return "小明入魔了,需要年轻貌美的女士来亲一口才可以恢复"
     34 
     35     def rolate_black(self):
     36         BlackSuperManXiaoMing.isNormal = False
     37         return "小明入魔了,快点唤醒他吧。 咒语是:xiaoming.call_me_back"
     38 
     39     def is_black(self):
     40         if BlackSuperManXiaoMing.isNormal:
     41             return "小明现在很正常"
     42         else:
     43             return "小明入魔了"
     44 
     45     def suddenly_black(self):
     46         return BlackInsideError("突然入魔")
     47 
     48     def black_to_white(self):
     49         print("小明发功中....")
     50         if random.randint(1,100000000)%4 < 2 :
     51             return "小明成功的压制了魔念"
     52         else:
     53             raise BlackInsideError("小明没有压制成功")
     54 
     55 if __name__ == '__main__':
     56 
     57     black = BlackSuperManXiaoMing("阿花")
     58     print(black.is_black())
     59     print(black.rolate_black())
     60     print(black.is_black())
     61     print(black.call_me_back())
     62     print(black.is_black())
     63 # ------------------------output--------------
     64 # 小明现在很正常
     65 # 小明入魔了,快点唤醒他吧。 咒语是:xiaoming.call_me_back
     66 # 小明入魔了
     67 # 小明入魔了,需要年轻貌美的女士来亲一口才可以恢复
     68 # 小明现在很正常
     69 
     70     b = black.suddenly_black()
     71     if isinstance(b, BlackInsideError):
     72         print ("小明异常了")
     73         print (b)
     74     else:
     75         print ("呵呵哒")
     76 # ------------------------output--------------
     77 # 小明异常了
     78 # 突然入魔,每次入魔小明都会干出奇怪而可怕的事情
     79 
     80     for i in range(10):
     81         b = black.black_to_white()
     82         if isinstance(b, BlackInsideError):
     83             print (b)
     84         else:
     85             print ("Oh yeah! {}".format(b))
     86 # ------------------------output--------------
     87 # 小明发功中....
     88 #小明成功的压制了魔念
     89 # 小明发功中....
     90 # Traceback (most recent call last):
     91 #   File "C:/Users/thinkpad/PycharmProjects/test_proto/test_xiaoming/SuperXiaoMing.py", line 62, in <module>
     92 #     b = black.black_to_white()
     93 #   File "C:/Users/thinkpad/PycharmProjects/test_proto/test_xiaoming/SuperXiaoMing.py", line 43, in black_to_white
     94 #     raise BlackInsideError("小明没有压制成功")
     95 # __main__.BlackInsideError: 小明没有压制成功,每次入魔小明都会干出奇怪而可怕的事情
     96 
     97     try:
     98         for i in range(10):
     99 
    100             b = black.black_to_white()
    101             if isinstance(b, BlackInsideError):
    102                 print (b)
    103             else:
    104                 print ("Oh yeah! {}".format(b))
    105     except:
    106         # 兼容错误,并忽略
    107         print ("小明入魔了,完犊子了")
    108         # pass指的是后续该代码块后续的部分,这里无实际意义
    109         pass
    110     else:
    111         print ("小明已经累计10次压制成功了")
    112     finally:
    113         print ("本次压制结束")
    114 # ------------------------output--------------
    115 #小明发功中....
    116 # Oh yeah! 小明成功的压制了魔念
    117 # 小明发功中....
    118 # Oh yeah! 小明成功的压制了魔念
    119 # 小明发功中....
    120 # Oh yeah! 小明成功的压制了魔念
    121 # 小明发功中....
    122 # Oh yeah! 小明成功的压制了魔念
    123 # 小明发功中....
    124 # Oh yeah! 小明成功的压制了魔念
    125 # 小明发功中....
    126 # Oh yeah! 小明成功的压制了魔念
    127 # 小明发功中....
    128 # Oh yeah! 小明成功的压制了魔念
    129 # 小明发功中....
    130 # Oh yeah! 小明成功的压制了魔念
    131 # 小明发功中....
    132 # 小明入魔了,完犊子了
    133 # 本次压制结束

    python异常综述:

    python中异常大致可以分为3类:

    • 系统级别的异常
      • 强制结束进程
        • SystemExit
      • 键盘Ctrl-C 退出
        • KeyboardInterrupt
      • 对象异常销毁
        • GeneratorExit
    • 可忽略的异常
      • 各种Warning,比如定义一些不用的变量之类,多见于IDE,直接脚本run不常见。可忽略
    • 代码级崩溃异常
      • 各种Error

    各Exception的调用关系如下:

        BaseException
         +-- SystemExit
         +-- KeyboardInterrupt
         +-- GeneratorExit
         +-- Exception
              +-- StopIteration
              +-- StandardError
              |    +-- BufferError
              |    +-- ArithmeticError
              |    |    +-- FloatingPointError
              |    |    +-- OverflowError
              |    |    +-- ZeroDivisionError
              |    +-- AssertionError
              |    +-- AttributeError
              |    +-- EnvironmentError
              |    |    +-- IOError
              |    |    +-- OSError
              |    |         +-- WindowsError (Windows)
              |    |         +-- VMSError (VMS)
              |    +-- EOFError
              |    +-- ImportError
              |    +-- LookupError
              |    |    +-- IndexError
              |    |    +-- KeyError
              |    +-- MemoryError
              |    +-- NameError
              |    |    +-- UnboundLocalError
              |    +-- ReferenceError
              |    +-- RuntimeError
              |    |    +-- NotImplementedError
              |    +-- SyntaxError
              |    |    +-- IndentationError
              |    |         +-- TabError
              |    +-- SystemError
              |    +-- TypeError
              |    +-- ValueError
              |         +-- UnicodeError
              |              +-- UnicodeDecodeError
              |              +-- UnicodeEncodeError
              |              +-- UnicodeTranslateError
              +-- Warning
                   +-- DeprecationWarning
                   +-- PendingDeprecationWarning
                   +-- RuntimeWarning
                   +-- SyntaxWarning
                   +-- UserWarning
                   +-- FutureWarning
               +-- ImportWarning
               +-- UnicodeWarning
               +-- BytesWarning
    

    异常捕获与优雅滚回

    • 通用兼容

      • 如果是以Exception对象返回,就
        • 使用if obj: …
        • 使用 isinstance(obj, Exception)
      • 如果是raise Exception,或者 代码Exception直接出来
        • 使用try…except…else…finally
    • 可回滚式兼容

      • with xxx as obj:
      • 优雅而从容,装逼利器

    with操作(文件操作为例)

    简单写法1.0

    f = open("openedfile","r")
    content = f.read()
    f.close()

    这种写法不存在任何健壮性,代码中存在的可能异常的地方有:

    • 文件件不存在
    • 没有读取权限
    • 读取过程中被篡改内容
    • 文件对象句柄忘记关闭等

    改进写法1.1

    解决问题1,2,4

    try:
        f = open("openedfile","r")
    except Exception as e:
        print ("file opened fail! ")
        print (e)
    else:
        content = f.read()
        f.close()

    改进写法1.2

    解决问题1,2,3,4

    try:
        f = open("openedfile","r")
        content = f.read()
    except Exception as e:
        print ("file opened fail! ")
        print (e)
    else:
        f.close()

    改进写法2.0

    with open("openedfile") as f:
        content = f.close()

    说明:

    • with是一种原子性操作,with里面的内容在失败后可以自动进行回滚,目前file、db等大多数欧快都自动支持with回滚
    • with可以和yeild进行对照理解

    with 工作原理简单解释

    with 语句会先调用 with obj 中obj.enter()方法进行初始化操作,然后开始执行with中的代码块。
    如果执行完成/失败,会调用obj中的obj.exit()方法进行退出

    So,我们也可以自己定义一些可被with的类给使用者友好调用。

    #! coding:utf-8
    class XiaoMing(object):
        angry = 0
        def __enter__(self):
            '''
                返回对向自己
            :return:
            '''
            print ("我是小明,地球的保护神")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            '''
                场景恢复,回滚等操作
            :param exc_type:  过程中的异常class
            :param exc_val:     异常类中的value,即说明
            :param exc_tb:  异常中的堆栈信息,即通常看到的trace back d对象
            :return: 返回True表示已经自己回滚完成,不需要外部额外处理;返回False表示需要外部捕获Exception
            '''
            XiaoMing.angry = 0
            print ("执行结束,请退出")
            print ("exc_type : {}, exc_val : {}, exc_tb : {}".format(exc_type, exc_val, exc_tb))
            print (dir(exc_tb))
            return True
    
        def excep(self):
            XiaoMing.angry = 999999
            a = 1/0
    
    xiaoming =  XiaoMing()
    # print (dir(xiaoming))
    with xiaoming:
        print ("小明很牛逼啊")
        xiaoming.excep()
    
    print ("after with, I'm here")
    
    #--------------output-------------------
    # 我是小明,地球的保护神
    # 小明很牛逼啊
    # 执行结束,请退出
    # exc_type : <class 'ZeroDivisionError'>, exc_val : division by zero, exc_tb : <traceback object at 0x06358940>
    # ['tb_frame', 'tb_lasti', 'tb_lineno', 'tb_next']
    # after with, I'm here

    引申阅读:

  • 相关阅读:
    vue-cli 安装一直失败
    如果不存在公缀,返回空字符串
    .sh文件格式问题dos转linux或unix
    Kettle串联多个Spark任务
    云效自动化部署+部署包备份
    云效分支管理
    云效IDE综合插件Alibaba Cloud Toolkit
    流水线自动化部署-中转部署-目标机器不联网情况下应用
    云效流水线自动化部署
    云效流水线自动发布到Maven仓
  • 原文地址:https://www.cnblogs.com/SilenceCity/p/pythonOO4.html
Copyright © 2020-2023  润新知