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