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