異常概述
異常指的是不正常,也就是程式在執行過程中發生了不可預知的問題,導致程式崩潰。Python中常見的異常類如下,它們都直接或者間接繼承自位於builtins.py檔案中的Exeption類
NameErrorTypeErrorValueErrorAttributeErrorSyntaxErrorIndexError異常處理在日常開發中應該儘量避免異常出現,而程式中可能發生異常的情況,可以透過Pyhton提供的異常處理機制來處理異常,從而提高程式的容錯性。
異常處理的語法格式為
try: 可能發生異常的程式碼except Exception: 當異常發生時,處理異常的程式碼
例如當使用字串的index(self, sub, start=None, end=None):方法來查詢子串時,如果指定的子串找不到會丟擲一個ValueError異常
此時可以使用try/except來處理ValueError的異常,如果異常的型別不確定時可以使用Exception替換,例如這裡的ValueError可以使用Exception替換,因為異常都直接或者間接繼承Exception
"""使用try/except基本異常處理@author tony [email protected]@version 2021-02-15 15:38:20@since python3.9.1"""s = "hello"# 使用try來嘗試執行可能發生異常的程式碼try: # ValueError: substring not found i = s.index("O") print(i)# 如果發生異常,那麼異常資訊會被except捕捉到,可以在except後面進行異常處理,如果沒有發生異常,程式正常執行,而except就不會執行except ValueError: print("查詢的子串不存在")
程式執行結果
專案執行過程中可能會發生多個異常,此時可以將多個異常包裝成一個元祖。需要注意的是同一時刻只能有一個異常發生,因為只要有一個異常發生,程式不會再往下執行,轉而執行except的異常處理的程式碼。
try: 可能發生異常的程式碼except (異常1,異常2....)as e: 當異常發生時,處理異常的程式碼
其中as e表示給異常起別名
"""多異常處理@author tony [email protected]@version 2021-02-15 16:09:54@since python3.9.1"""try: number / 0except(ZeroDivisionError, NameError) as e: print("程式出現了異常", e)
程式執行結果
而異常處理的完整語法格式,其中else和finally都是可選的,而finally通常是操作檔案、資料庫或者網路時關閉資源使用
try: 可能出現異常的程式碼except Exception as e: 異常處理的程式碼else: 沒有出現異常的程式碼finally: 無論是否出現異常,都會執行此語句塊
異常處理之 try/except/else/finally:檔案不存在異常
"""異常處理之 try/except/else/finally@author tony [email protected]@version 2021-02-15 16:16:37@since python3.9.1"""try: f = None f = open("java.txt", "r")except Exception as e: print("要開啟的檔案不存在") print("異常資訊是", e)else: content = f.read(1024) print("檔案內容是", end="\t") print(content)finally: print("無論程式是否有異常都會執行finally") if f != None: print("關閉檔案資源") f.close()
程式執行結果
異常處理之 try/except/else/finally:檔案存在並關閉檔案資源
"""異常處理之 try/except/else/finally@author tony [email protected]@version 2021-02-15 16:16:37@since python3.9.1"""try: f = None f = open("python.txt", "r")except Exception as e: print("要開啟的檔案不存在") print("異常資訊是", e)else: content = f.read(1024) print("檔案內容是", end="\t") print(content)finally: print("無論程式是否有異常都會執行finally") if f != None: print("關閉檔案資源") f.close()
程式執行結果
異常傳遞當代碼出現多個層級呼叫時,其中如果某個環節發生了異常,但是該異常沒有處理,預設情況下該異常會向上丟擲,如果上層也沒有處理,那麼會繼續再向上層丟擲,直到拋到直譯器,直譯器預設的處理方式就是中斷程式,將異常資訊列印輸出到終端上。
"""異常傳遞@author tony [email protected]@version 2021-02-15 15:59:32@since python3.9.1"""def func_a(): print("execute func_a function") func_b()def func_b(): print("execute func_b function") func_c()def func_c(): print("execute func_c function") result = 1 / 0 print(result)func_a()
程式執行結果
此時推薦在func_c()方法處理該異常
"""異常傳遞@author tony [email protected]@version 2021-02-15 15:59:32@since python3.9.1"""def func_a(): print("execute func_a function") func_b()def func_b(): print("execute func_b function") func_c()def func_c(): print("execute func_c function") try: result = 1 / 0 print(result) except ZeroDivisionError: print("0不能作為被除數")func_a()
程式執行結果
當然由於異常的傳遞機制,也可以在func_b()方法或者是func_a()方法來處理異常
"""異常傳遞@author tony [email protected]@version 2021-02-15 15:59:32@since python3.9.1"""def func_a(): print("execute func_a function") func_b()def func_b(): print("execute func_b function") try: func_c() except ZeroDivisionError: print("0不能作為被除數")def func_c(): print("execute func_c function") result = 1 / 0 print(result)func_a()
程式執行結果
自定義異常在業務開發時需要根據對應的業務場景來自定義相關的業務異常。
自定義異常的語法格式
class 異常名Error(Exception): pass
自定義異常
"""定義一個手機號不是純數字異常"""class PhoneNumberNotDigitError(Exception): pass"""定義一個手機號長度不合法異常"""class PhoneNumberLengthError(Exception): def __init__(self, msg): self.__msg = msg def __str__(self): return self.__msg pass
系統異常通常是由系統丟擲,而自定義異常通常由開發人員手動丟擲,其方式是 raise 異常物件,異常物件可以是類物件,也可以是例項物件
def get_phone_number(): """ 從鍵盤獲取使用者輸入的手機號,判斷是否合法 :return: """ phone_number = input("請輸入一個11位數字的手機號:") if phone_number.isdigit() == False: # 丟擲自定義的異常 異常物件是類物件 raise PhoneNumberNotDigitError elif len(phone_number) != 11: # 丟擲自定義異常,異常物件是例項物件 raise PhoneNumberLengthError("異常資訊:手機號長度必須是11位") return phone_number
透過匯入模組呼叫get_phone_number()函式來處理自定義異常
"""處理自定義異常@author tony [email protected]@version 2021-02-15 16:49:50@since python3.9.1"""from custom_exception import *# 處理呼叫get_phone_number()函式時可能發生的異常try: phone_number = get_phone_number()except (PhoneNumberLengthError, PhoneNumberNotDigitError) as e: print(e)else: print("你輸入的手機號是", phone_number)
程式執行結果