""" 異常處理 """ __author__on__ = 'shaozhiqi 2019/9/19' # 大量的代碼來判斷是否出錯: # def foo(): # r = some_function() # if r == (-1): # return (-1) # # do something # return r # # # def bar(): # r = foo() # if r == (-1): # print('Error') # else: # pass # 用異常機制來處理 try: print('try...') r = 10 / 0 print('result:', r) except ZeroDivisionError as e: print('except:', e) # 執行結果: except: division by zero finally: print('finally...') print('END') # 我們認為某些代碼可能會出錯時,就可以用try來運行這段代碼, # 如果執行出錯,則后續代碼不會繼續執行,而是直接跳轉至錯誤處理代碼, # 即except語句塊,執行完except后,如果有finally語句塊,則執行finally語句塊,至此,執行完畢。 # ----------------------------------------------------------------------------- # 如果沒有錯誤發生,可以在except語句塊后面加一個else,當沒有錯誤發生時,會自動執行else語句: try: print('try...') r = 10 / int('2') print('result:', r) except ValueError as e: print('ValueError:', e) except ZeroDivisionError as e: print('ZeroDivisionError:', e) else: print('no error!') finally: print('finally...') print('END') # 執行結果: # try... # result: 5.0 # no error! # finally... # END # 異常列表:https://docs.python.org/3/library/exceptions.html#exception-hierarchy # ---------------------------------------------------------------- # 只要在最上層捕獲了,就可以處理 def foo(s): return 10 / int(s) def bar(s): return foo(s) * 2 def main(): try: bar('0') except Exception as e: print('Error:', e) finally: print('finally...') main() # 執行結果: # Error: division by zero # finally... # 不需要在每個可能出錯的地方去捕獲錯誤,只要在合適的層次去捕獲錯誤就可以了 # ------------------------------------------------------------------------- # 如果不捕獲錯誤,自然可以讓Python解釋器來打印出錯誤堆棧,但程序也被結束了。 # 既然我們能捕獲錯誤,就可以把錯誤堆棧打印出來,然后分析錯誤原因,同時,讓程序繼續執行下去。 import logging def foo(s): return 10 / int(s) def bar(s): return foo(s) * 2 def main(): try: bar('0') except Exception as e: logging.exception(e) main() print('END') # --------------------------------------------------------------------- # 自定義異常,並拋出自定義異常,不捕獲的話程序中斷 class FooError(ValueError): pass def foo(s): n = int(s) if n == 0: raise FooError('invalid value: %s' % s) return 10 / n # foo('0') # __main__.FooError: invalid value: 0 # 拋出系統異常 def foo(s): n = int(s) if n == 0: raise ValueError('invalid value: %s' % s) return 10 / n def bar(): try: foo('0') except ValueError as e: print('ValueError!') raise bar() # ValueError: invalid value: 0 # 捕獲錯誤目的只是記錄一下,便於后續追蹤。 # 由於當前函數不知道應該怎么處理該錯誤,所以,最恰當的方式是繼續往上拋,讓頂層調用者去處理。 # raise語句如果不帶參數,就會把當前錯誤原樣拋出。此外,在except中raise一個Error,還可以把一種類型的錯誤轉化成另一種類型: try: 10 / 0 except ZeroDivisionError: raise ValueError('input error!') # 切勿在業務中如上處理,這樣就不知道到底是啥異常了