Python進階|聊聊異常處理
- 2019 年 10 月 7 日
- 筆記

前言
在編寫代碼中,總會遇到一些bug和報錯,怎麼去捕獲這些異常,並進行處理,以讓程序更健碩了?本篇文章將帶你聊聊Python的異常處理。

錯誤與異常
編寫的程序出錯,至少有兩種可能,一是語法錯誤,二就是我們說的異常。
語法錯誤很好理解,就是我們寫的代碼不符合Python代碼的規範,導致程序無法識別和運行,比如下面這個例子:
def add(a,b) print(a+b) add(1,2) #SyntaxError: invalid syntax
我們定義函數漏掉了冒號,所以導致出錯,報錯為SyntaxError。
而異常是指本身的程序編寫沒有錯誤,在執行中出現了問題,拋出了異常,比如我們都知道0不能作為分母,那我們把0當為分母,就會拋出異常ZeroDivisionErro。
1/0 # ZeroDivisionError: division by zero
我們在看看其他的異常類型:
1 + 'a' # TypeError: unsupported operand type(s) for +: 'int' and 'str' print(name) #NameError: name 'name' is not defined
當然Python還有很多其他的異常類型,可以參考Python的官方文檔進行查看(https://docs.python.org/3/library/exceptions.html#bltin-exceptions)
處理異常
我們都知道,拋出異常後,整個程序就會被終止,當然理想情況下,我們是希望程序不被終止,而是捕捉到這次異常。
當然Python有這樣的語法來實現並處理異常,這就是try和except來解決。
try: 嘗試運行程序 出現異常後這段代碼就不會運行 except 錯誤類 as e: 發生異常運行這部分代碼
我們就拿0不能作為分母來進行演示:
try: a = 1/0 print(a) except ZeroDivisionError as e: print("錯誤:{}".format(e)) #錯誤:division by zero
這裡我們需要注意的是,如果程序的異常與except中定義的異常不匹配時,程序還是會報錯,例如:
try: print(name) except ZeroDivisionError as e: print("錯誤:{}".format(e)) # NameError: name 'name' is not defined
所以,當我們有多個異常錯誤時,這種寫法就有局限性,我們可以這樣來寫:
#第一種方法 try: print(1/0) print(name) except (ZeroDivisionError,NameError) as e: print("錯誤:{}".format(e)) #第二種方法 try: print(1/0) print(name) except ZeroDivisionError as e: print("錯誤:{}".format(e)) except NameError as e: print("錯誤:{}".format(e)) # 錯誤:division by zero
細心的讀者可能會發現,我們程序運行的結果是表示捕捉到了0不能為分母的錯誤,那NameError為什麼沒有被捕捉到了?
那是因為程序存在多個except異常時,程序最多只有一個會被執行並捕捉,簡單的說,最先捕捉的異常會被執行,其他都會被忽略。
那有時候我們事先並不知道有多少異常,應該怎麼處理了?我們可以用Exception,他是其他非系統異常的基類。或者在except語句塊後面不加異常類。
try: print(1/0) print(name) except Exception as e: print("錯誤:{}".format(e)) try: print(1/0) print(name) except: print("錯誤")
最後,我們看看finally,其作用是不管有無異常,finally內的語句都會被執行。
try: f = open('test.txt','r') except: print('erro') finally: f.close()
這裡讀取文件,不管是否出現異常,都會執行關閉文件的操作。
主動拋出異常
我們可以通過raise語句主動拋出異常,其用法為:raise 後跟要拋出的異常。這個異常必須是異常實例或者是一個異常類。
那我們通過raise玩個好玩的事情,0不能為分母的異常提示是英文的,我自己主動拋出個異常,換為中文提示。
try: raise ZeroDivisionError('分母不能為零!!') except ZeroDivisionError as e: print('錯誤:{}'.format(e)) # 錯誤:分母不能為零!!
自定義異常類
如果Python內置的異常類型不滿足我們的需求時,我們可以自定義異常類。但我們需要注意的是,所有內置的非系統退出類異常都派生Exception類, 所有用戶自定義異常也應當派生自此類。
簡單的說,我們自己寫的異常類必須直接或間接集成Exception類。
例如:
class MyError(Exception): def __init__(self,value): self.value = value def __str__(self): return '{} is error'.format(repr(self.value)) try: raise MyError(1) except MyError as e: print(e) # 1 is error
兩個魔法方法: def init(self),異常類對象的初始化屬性; def str(self),返回異常類對象說明信息。
總結
- 錯誤與異常
- 異常處理
- 拋出異常
- 自定義異常