Python中的異常處理以及自定義異常類型方式
異常
程序在運行過程當(dāng)中,不可避免的會出現(xiàn)一些錯誤,比如:
- 使用了沒有賦值過的變量
- 使用了不存在的索引
- 除0
- …
- 這些錯誤在程序中,我們稱其為異常。
程序運行過程中,一旦出現(xiàn)異常將會導(dǎo)致程序立即終止,異常以后的代碼全部都不會執(zhí)行!
處理異常
程序運行時出現(xiàn)異常,目的并不是讓我們的程序直接終止!
Python是希望在出現(xiàn)異常時,我們可以編寫代碼來對異常進(jìn)行處理!
try語句
try:
代碼塊(可能出現(xiàn)錯誤的語句)
except 異常類型 as 異常名:
代碼塊(出現(xiàn)錯誤以后的處理方式)
except 異常類型 as 異常名:
代碼塊(出現(xiàn)錯誤以后的處理方式)
except 異常類型 as 異常名:
代碼塊(出現(xiàn)錯誤以后的處理方式)
else:
代碼塊(沒出錯時要執(zhí)行的語句)
finally:
代碼塊(該代碼塊總會執(zhí)行)
try是必須的 else語句有沒有都行
except和finally至少有一個
可以將可能出錯的代碼放入到try語句,這樣如果代碼沒有錯誤,則會正常執(zhí)行,
如果出現(xiàn)錯誤,則會執(zhí)行expect子句中的代碼,這樣我們就可以通過代碼來處理異常
避免因為一個異常導(dǎo)致整個程序的終止
異常的傳播(拋出異常)
當(dāng)在函數(shù)中出現(xiàn)異常時,如果在函數(shù)中對異常進(jìn)行了處理,則異常不會再繼續(xù)傳播,
如果函數(shù)中沒有對異常進(jìn)行處理,則異常會繼續(xù)向函數(shù)調(diào)用處傳播,
如果函數(shù)調(diào)用處處理了異常,則不再傳播,如果沒有處理則繼續(xù)向調(diào)用處傳播
直到傳遞到全局作用域(主模塊)如果依然沒有處理,則程序終止,并且顯示異常信息
當(dāng)程序運行過程中出現(xiàn)異常以后,所有的異常信息會被保存一個專門的異常對象中,而異常傳播時,實際上就是異常對象拋給了調(diào)用處
比如 : ZeroDivisionError類的對象專門用來表示除0的異常
NameError類的對象專門用來處理變量錯誤的異常
…等等
當(dāng)程序運行時,如果沒有進(jìn)行異常處理,異常會一直傳播,直到傳遞到全局作用域(主模塊),此時程序會終止并顯示異常信息。
下面是一個示例:
def fn(): raise ValueError("這是一個自定義的異常") def main(): try: fn() except ValueError as e: print("發(fā)生了異常:", e) main() print("程序結(jié)束")
在上面的代碼中,fn()
函數(shù)中使用raise
語句拋出了一個ValueError
異常,并指定了異常信息為"這是一個自定義的異常"。
在main()
函數(shù)中,使用try-except
語句捕獲了ValueError
異常,并打印出異常信息。
最后,輸出"程序結(jié)束"。
拋出異常
可以使用 raise 語句來拋出異常,
raise語句后需要跟一個異常類 或 異常的實例
當(dāng)在代碼中使用異常處理時,我們可以使用raise
語句來引發(fā)自定義的異?;蛑匦乱l(fā)已捕獲的異常。
下面是一個示例:
def divide(x, y): try: if y == 0: raise ZeroDivisionError("除數(shù)不能為零") result = x / y except ZeroDivisionError as e: print(e) raise # 重新引發(fā)已捕獲的異常 else: print("結(jié)果:", result) try: divide(10, 2) divide(10, 0) except ZeroDivisionError as e: print("捕獲異常:", e)
在上述代碼中,當(dāng)除數(shù)為零時,我們通過raise
語句引發(fā)了內(nèi)置的ZeroDivisionError
異常,并傳入錯誤消息。
同時,在except ZeroDivisionError
塊中使用raise
語句重新引發(fā)已捕獲的異常,以便在外部繼續(xù)處理該異常。
在使用引發(fā)異常時,我們可以選擇傳遞一個異常類的實例或使用類名直接引發(fā)該異常。
在本例中,我們使用了后者,即raise ZeroDivisionError("除數(shù)不能為零")
。
在主代碼塊中,我們用try-except
來捕獲ZeroDivisionError
異常,并打印出捕獲的異常信息。
這樣就能夠處理由divide()
函數(shù)引發(fā)的異常。
輸出如下:
結(jié)果: 5.0
division by zero
捕獲異常: division by zero
通過使用raise
語句,我們可以在代碼中顯式地引發(fā)異常,并根據(jù)需要進(jìn)行處理或傳遞。
這使得異常處理更加靈活和可控,有助于編寫健壯的代碼。
try-except語句
在Python中,我們可以使用try-except
語句來捕獲并處理指定類型的異常。
除了捕獲特定類型的異常外,我們還可以使用try-except
語句的多個except
塊來分別處理不同類型的異常。
下面是一個示例:
def divide(x, y): try: result = x / y print("結(jié)果:", result) except ZeroDivisionError: print("除數(shù)不能為零") except TypeError: print("類型錯誤:無法進(jìn)行除法運算") except ValueError: print("數(shù)值錯誤") divide(10, 2) divide(10, 0) divide(10, "2")
在上述代碼中,divide()
函數(shù)用于計算兩個數(shù)的除法并打印結(jié)果。
在try
塊中進(jìn)行除法運算,如果出現(xiàn)異常,則根據(jù)異常類型執(zhí)行相應(yīng)的except
塊。
- 第一次調(diào)用
divide(10, 2)
時,由于除數(shù)不為零,沒有觸發(fā)異常,因此會輸出結(jié)果。 - 第二次調(diào)用
divide(10, 0)
時,除數(shù)為零,觸發(fā)了ZeroDivisionError
異常,程序會執(zhí)行對應(yīng)的except ZeroDivisionError
塊,打印"除數(shù)不能為零"。 - 第三次調(diào)用
divide(10, "2")
時,除數(shù)為字符串類型,無法進(jìn)行除法運算,觸發(fā)了TypeError
異常,程序會執(zhí)行對應(yīng)的except TypeError
塊,打印"類型錯誤:無法進(jìn)行除法運算"。
輸出如下:
結(jié)果: 5.0
除數(shù)不能為零
類型錯誤:無法進(jìn)行除法運算
通過使用多個except
塊,可以針對不同的異常類型編寫特定的處理代碼,使程序能夠更準(zhǔn)確地處理各種可能的異常情況。
這樣可以提高程序的健壯性和可靠性。
finally 語句
除了使用try-except
語句來處理異常以外,還可以使用finally
子句來定義無論是否發(fā)生異常都需要執(zhí)行的代碼塊。
finally
子句中的代碼塊會在try
塊中的代碼執(zhí)行完成后無論是否發(fā)生異常都會被執(zhí)行。
下面是一個示例:
def divide(x, y): try: result = x / y except ZeroDivisionError: print("除數(shù)不能為零") finally: print("執(zhí)行finally代碼塊") divide(10, 2) divide(10, 0)
在上述代碼中,divide()
函數(shù)用于計算兩個數(shù)的除法并打印結(jié)果,其中使用try-except-finally
語句來處理異常。
- 第一次調(diào)用
divide(10, 2)
時,由于除數(shù)不為零,沒有觸發(fā)異常,因此會輸出結(jié)果并執(zhí)行finally
代碼塊。
輸出如下:
結(jié)果: 5.0
執(zhí)行finally代碼塊
- 第二次調(diào)用
divide(10, 0)
時,除數(shù)為零,觸發(fā)了ZeroDivisionError
異常,異常被捕獲并打印錯誤信息,然后繼續(xù)執(zhí)行finally
代碼塊。
輸出如下:
除數(shù)不能為零
執(zhí)行finally代碼塊
可以看到,不論是否發(fā)生異常,finally
代碼塊中的代碼都會被執(zhí)行。
finally
子句通常用于釋放資源,例如關(guān)閉文件、釋放鎖等。
它確保不論是否發(fā)生異常,都會執(zhí)行一些必要的清理操作,以保證程序的穩(wěn)定性和安全性。
else語句
除了try-except
語句外,你還可以使用else
子句來定義在try
塊中沒有發(fā)生任何異常時執(zhí)行的代碼塊。
下面是一個示例:
def divide(x, y): try: result = x / y except ZeroDivisionError: print("除數(shù)不能為零") else: print("結(jié)果:", result) divide(10, 2) divide(10, 0)
在上述代碼中,divide()
函數(shù)用于計算兩個數(shù)的除法并打印結(jié)果。
在try
塊中進(jìn)行除法運算,如果出現(xiàn)除以零的異常,則程序會執(zhí)行對應(yīng)的except ZeroDivisionError
塊,打印"除數(shù)不能為零"。
如果沒有發(fā)生異常,程序會執(zhí)行else
子句中的代碼塊,打印結(jié)果。
- 第一次調(diào)用
divide(10, 2)
時,由于除數(shù)不為零,沒有觸發(fā)異常,因此會輸出結(jié)果。 - 第二次調(diào)用
divide(10, 0)
時,除數(shù)為零,觸發(fā)了ZeroDivisionError
異常,程序會執(zhí)行對應(yīng)的except ZeroDivisionError
塊,打印"除數(shù)不能為零",而不會執(zhí)行else
子句中的代碼塊。
輸出如下:
結(jié)果: 5.0
除數(shù)不能為零
通過使用else
子句,可以將正常處理邏輯放在else
中,使代碼更加清晰和簡潔。
這樣,我們可以清楚地區(qū)分異常處理和正常邏輯處理,提高代碼的可讀性和可維護(hù)性。
自定義異常類型
另外,如果我們需要自定義異常類型,可以通過繼承內(nèi)置的Exception
類來創(chuàng)建新的異常類型,并在需要拋出異常時使用該類型。
下面是一個示例:
class MyError(Exception): def __init__(self, msg): self.msg = msg def divide(x, y): try: if y == 0: raise MyError("除數(shù)不能為零") result = x / y except MyError as e: print(e.msg) else: print("結(jié)果:", result) finally: print("執(zhí)行清理操作") divide(10, 2) divide(10, 0)
在上述代碼中,我們通過繼承Exception
類創(chuàng)建了一個新的異常類型MyError
,并在其構(gòu)造函數(shù)中傳入一個錯誤消息。
在divide()
函數(shù)中,我們在除以零時拋出了自定義的異常MyError
,并捕獲并處理這個異常。
如果沒有發(fā)生異常,會執(zhí)行else
子句中的代碼塊,打印結(jié)果。
無論是否發(fā)生異常,最后都會執(zhí)行finally
子句中的代碼塊,打印"執(zhí)行清理操作"。
輸出如下:
結(jié)果: 5.0
執(zhí)行清理操作
除數(shù)不能為零
執(zhí)行清理操作
通過自定義異常類型,我們可以更好地組織和管理自己的代碼,提高代碼的可讀性和可維護(hù)性。同時,也能夠更加靈活地處理不同類型的異常情況,滿足不同的業(yè)務(wù)需求。
總結(jié)
本文介紹了Python中異常的使用和處理。異常是在程序執(zhí)行期間發(fā)生的錯誤或異常情況,可以通過使用try-except語句來捕獲和處理異常。
文章首先解釋了什么是異常,并且描述了異常處理的重要性。接著,介紹了如何使用try-except語句來捕獲并處理異常。try塊中的代碼可能引發(fā)異常,而except塊中的代碼將只有在相應(yīng)的異常發(fā)生時才會執(zhí)行。
文章還提到了finally語句,它允許我們定義一段無論是否發(fā)生異常都會執(zhí)行的代碼塊。這對于確保資源的釋放或清理非常有用。
此外,文章還介紹了else語句,它可以用于指定在try塊中沒有引發(fā)異常時執(zhí)行的代碼。這樣我們可以根據(jù)是否發(fā)生異常來采取不同的行動。
最后,文章也提到了自定義異常類型的重要性和使用方法。通過定義自己的異常類,我們可以更好地組織和處理特定的異常情況,使代碼更具可讀性和可維護(hù)性。
通過本文的介紹,讀者可以了解到如何在Python中處理異常以及如何利用異常機制編寫更健壯的代碼。同時,熟悉異常處理的相關(guān)概念和語法將幫助讀者更好地調(diào)試和處理程序中的錯誤情況。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何徹底解決python?NameError:name?'__file__'?is?not?
這篇文章主要給大家介紹了關(guān)于如何徹底解決python?NameError:name?'__file__'?is?not?defined的相關(guān)資料,文中通過圖文將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02Win10下安裝CUDA11.0+CUDNN8.0+tensorflow-gpu2.4.1+pytorch1.7.0+p
這篇文章主要介紹了Win10下安裝CUDA11.0+CUDNN8.0+tensorflow-gpu2.4.1+pytorch1.7.0+paddlepaddle-gpu2.0.0,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03跟老齊學(xué)Python之?dāng)?shù)據(jù)類型總結(jié)
前面已經(jīng)洋洋灑灑地介紹了不少數(shù)據(jù)類型。不能再不顧一切地向前沖了,應(yīng)當(dāng)總結(jié)一下。這樣讓看官能夠從總體上對這些數(shù)據(jù)類型有所了解,如果能夠有一覽眾山小的感覺,就太好了。2014-09-09