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
- 各种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
- 如果是以Exception对象返回,就
-
可回滚式兼容
- 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