在Python
中,使用異常物件(exception object)
來表示程式碼執行過程中所發生的異常情況,當執行程式爆出錯誤的時候則會拋出異常。
如果沒有正確處理異常,則會終止運行。
你可以想像一下,如果你在開發一款產品時,出現異常而不報告出發生異常的原因,是不是會很難受,也很難解決異常的問題。
為了提高產品的穩定性與靈活性,Python
運行開發者捕捉並處理各類異常,一般的內部模組報錯如KeyError異常類別
較為常見,當然也有很多其他的。
簡單了解下,Python將程式碼執行錯誤分為兩類:語法錯誤(syntax error)
與例外(exception)
。
首先,是語法錯誤的問題。字面可知,程式碼解析錯誤。
這種錯誤通常出現在初學者,主要原因是所執行的程式碼不符合Python語法的規範,故會報出語法錯誤導致code停機。
下面給出一個錯誤示範:
>>> if for not in list(1,2,3,4) File "<stdin>", line 1 if for not in list(1,2,3,4) ^ SyntaxError: invalid syntax
從上面的報錯可以知道是語法錯誤,無效的語法。並且指出了錯誤的地方在for
的位置,很顯然if
和for
不能用在一起。
異常則是在程式碼執行過程中發現的錯誤,這是很難提前被發現的,即使程式碼寫的很規範標準,但也可能會出現執行異常的情況。
下面給出一個錯誤範例。在數學運算中,經常討論的問題是除數為零的情況。然而,0作為除數是不被允許的,因為這樣會導致異常情況。
>>> a = 5 / 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero
很明顯報錯指出0作為除數是不對的。
當我們了解了錯誤和異常後,就得處理異常情況。對於語法錯誤這種問題多練習即可避免,對於第二種異常,python
給了try-except
語句來處理。
為了更清晰的解釋,還是以上面的除數為0的情況作為例子,我們透過添加try-except
語句來捕捉並處理異常情況:
def division(x, y): try: return x / y except ZeroDivisionError: print("0不能作为除数!!!")
然後我們再在terminal呼叫函數試試:
division(x=1, y=0)
輸出:
0不能當除數! ! !
雖然我們的輸入是錯誤的理論應該要報錯,但是並沒有報錯而且還回傳了一段話。
下面解釋一下try-except
語句的工作原理:
#Try-except中的程式碼會被正常執行
如果沒有出現異常則跳過except程式碼區塊並結束try-except
#如果try-except中的某一句程式碼出現了問題異常,剩餘程式碼停止執行,如果出現的異常與except所指定的一致,則執行except中的程式碼區塊,異常處理結束整個應用程式繼續執行
如果出現的例外與except中指定的不符合,那麼則跳出try語句,程式繼續拋出異常並終止執行程式碼
當然,我們所寫的程式碼可能會出現多種異常情況,因此我們可以將所有的異常情況寫在一個except語句區塊中,具體實作如下:
except (RuntimeError, TypeError, NameError):pass
如果捕捉到異常列表中的任一項異常表達式,則都會進入except
處理。
當然,如果你想對每一種異常進行單獨處理也可以一個一個的分開進行處理:
def passpass(x=1): try: return print(x+x) except (RuntimeError, TypeError, NameError): pass except TypeError: print('参数错误啦~') except NameError: print('名称错误啦~')
今天先到這裡明兒再更,去跳繩了,哎,每天捲捲,老北京雞內捲啊~(2022.4.20)
Python的異常類型是可以繼承的, 我們在此僅需知道,若except後指定的異常繼承自前面異常,由此後面的異常也會被捕捉到,範例如下:
class A(Exception): pass class B(A): pass class C(B): pass for cls in [A, B, C]: try: raise cls() except C: print('C') except B: print('B') except A: print('A')
則會輸出:
A
B
C
相反,如果把except的順序倒過來,則只會輸出A,由於異常B和C都繼承來自A,由此在捕捉到B異常後則會終止:
class A(Exception): pass class B(A): pass class C(B): pass for cls in [A, B, C]: try: raise cls() except A: print('A') except B: print('B') except C: print('C')
輸出全為A:
A
A
A
如果所有異常都一一的提取出來,這會很麻煩,此時可以在最後的一個except中不設定異常類型,因此剩下沒有被捕獲的異常全會被捕捉:
def passpass(x=1): try: return print(x/x) except TypeError: print('参数错误啦~') except NameError: print('名称错误啦~') except: print('报错啦~自己查')
一個重要功能:else.
else語句則是用來執行一些額外操作,如try程式碼區塊中執行了一些檔案操作,在else中可以釋放資源,else的語法格式如下:
try: pass except: pass else: pass
當然我們還可以操作異常,如下:
def passpass(x=1): try: return print(x/x) except TypeError as error: print('参数错误啦~', error) except NameError: print('名称错误啦~') except: print('报错啦~自己查')
開發者在平常的有些情況下並沒有執行錯誤,但是不符合設計邏輯,由此需要開發者主動拋出異常,這時我們需要使用raise語句拋出異常:
>>> raise NameError('HiThere') Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: HiThere
Python內建異常無法滿足開發需求的時候,可以自訂異常。
自定义异常类必须要直接或间接继承自Exception类。尽管自定义异常类与其他类具有相同的功能,但为保持简洁,应该仅提高必要的属性。
class Error(Exception): """Base class for exception in this module.""" pass class InputError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the winerror """ def __init__(self, expression, message): self.expression = expression self.message = message
else在代码正常执行后才会被执行的代码块,但有些情况无论代码块是否出现异常都要执行,则需要用到finally语句:
def passpass(x=1): try: return print(x/x) except TypeError as error: print('参数错误啦~', error) except NameError: print('名称错误啦~') except: print('报错啦~自己查') finally: print('运算结束~')
以上是Python基礎教程異常處理的方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!