編寫代碼時能否手動拋出一個異常嗎?答案是肯定的,Python 允許程序自行引發異常,使用 raise 語句即可?;菊Z法格式為:
raise[exceptionName[(reason)]]
其中,用 [] 括起來的為可選參數,其作用是指定拋出的異常名稱,以及異常信息的相關描述。如果可選參數全部省略,則 raise 會把當前錯誤原樣拋出;如果僅省略 (reason),則在拋出異常時,將不附帶任何的異常描述信息。
也就是說,raise 語句有如下三種常用的用法:
1、raise:單獨一個 raise。該語句引發當前上下文中捕獲的異常(比如在 except 塊中),或默認引發 RuntimeError 異常。
2、raise 異常類名稱:raise 后帶一個異常類名稱。該語句引發指定異常類的默認實例。
3、raise 異常類名稱(描述信息):在引發指定異常的同時,附帶異常的描述信息。
上面三種用法最終都是要引發一個異常實例(即使指定的是異常類,實際上也是引發該類的默認實例),raise 語句每次只能引發一個異常實例。
例如:
>>>raiseTraceback(mostrecentcalllast):File"<pyshell#1>",line1,in<module>raiseRuntimeError:Noactiveexceptiontoreraise>>>raiseZeroDivisionErrorTraceback(mostrecentcalllast):File"<pyshell#0>",line1,in<module>raiseZeroDivisionErrorZeroDivisionError>>>raiseZeroDivisionError("除數不能為零")Traceback(mostrecentcalllast):File"<pyshell#2>",line1,in<module>raiseZeroDivisionError("除數不能為零")ZeroDivisionError:除數不能為零
注意,即使是用戶自行引發的異常,也可以使用 try except 來捕獲它。當然也可以不管它,讓該異常向上(先調用者)傳播,如果該異常傳到 Python 解釋器,那么程序就會中止。
下面示例示范了處理用戶引發異常的兩種方式:
defmain():try:#使用try...except來捕捉異常#此時即使程序出現異常,也不會傳播給main函數mtd(3)exceptExceptionase:print('程序出現異常:',e)#不使用try...except捕捉異常,異常會傳播出來導致程序中止mtd(3)defmtd(a):ifa>0:raiseValueError("a的值大于0,不符合要求")main()
從上面程序可以看到,程序既可在調用 mtd(3) 時使用 try except 來捕獲異常,這樣該異常將會被 except 塊捕獲;也可直接調用 mtd(3),這樣該函數的異常就會直接導致程序中止。
運行上面程序,可以看到如下輸出結果:
程序出現異常: a的值大于0,不符合要求
Traceback(mostrecentcalllast):File"C:\Users\mengma\Desktop\1.py",line13,in<module>main()File"C:\Users\mengma\Desktop\1.py",line9,inmainmtd(3)File"C:\Users\mengma\Desktop\1.py",line12,inmtdraiseValueError("a的值大于0,不符合要求")ValueError:a的值大于0,不符合要求
上面第一行輸出是第一次調用 mtd (3) 的結果,該方法引發的異常被 except 塊捕獲并處理。后面的大段輸出則是第二次調用 mtd(3) 的結果,由于該異常沒有被 except 塊捕獲,導致程序中止。
第二次調用 mtd(3) 引發的以“File”開頭的三行輸出,其實顯示的就是異常的傳播軌跡信息。也就是說,如果程序不對異常進行處理,Python 默認會在控制臺輸出異常的傳播軌跡信息。
raise 不需要參數
正如前面所看到的,在使用 raise 語句時可以不帶參數,此時 raise 語句處于 except 塊中,它將會自動引發當前上下文激活的異常;否則,通常默認引發 RuntimeError 異常。
例如,將上面程序改為如下形式:
classAuctionException(Exception):passclassAuctionTest:def__init__(self,init_price):self.init_price=init_pricedefbid(self,bid_price):d=0.0try:d=float(bid_price)exceptExceptionase:#此處只是簡單地打印異常信息print("轉換出異常:",e)#再次引發自定義異常raiseifself.init_price>d:raiseAuctionException("競拍價比起拍價低,不允許競拍!")initPrice=ddefmain():at=AuctionTest(20.4)try:at.bid("df")exceptAuctionExceptionasae:#再次捕獲到bid()方法中的異常,并對該異常進行處理print('main函數捕捉的異常:',ae)main()
正如從 13 行代碼所看到的,此時程序在 except 塊中只是簡單地使用 raise 語句來引發異常,那么該 raise 語句將會再次引發該 except 塊所捕獲的異常。運行該程序,可以看到如下輸出結果:
轉換出異常:couldnotconvertstringtofloat:'df'main函數捕獲的異常:<class'ValueError'>
從輸出結果來看,此時 main() 函數再次捕獲了 ValueError,它就是在 bid() 方法中 except 塊所捕獲的原始異常。
except 和 raise 同時使用
在實際應用中對異??赡苄枰鼜碗s的處理方式。當一個異常出現時,單靠某個方法無法完全處理該異常,必須由幾個方法協作才可完全處理該異常。也就是說,在異常出現的當前方法中,程序只對異常進行部分處理,還有些處理需要在該方法的調用者中才能完成,所以應該再次引發異常,讓該方法的調用者也能捕獲到異常。
為了實現這種通過多個方法協作處理同一個異常的情形,可以在 except 塊中結合 raise 語句來完成。如下程序示范了except 和 raise 同時使用的方法:
classAuctionException(Exception):passclassAuctionTest:def__init__(self,init_price):self.init_price=init_pricedefbid(self,bid_price):d=0.0try:d=float(bid_price)exceptExceptionase:#此處只是簡單地打印異常信息print("轉換出異常:",e)#再次引發自定義異常raiseAuctionException("競拍價必須是數值,不能包含其他字符!")#①raiseAuctionException(e)ifself.init_price>d:raiseAuctionException("競拍價比起拍價低,不允許競拍!")initPrice=ddefmain():at=AuctionTest(20.4)try:at.bid("df")exceptAuctionExceptionasae:#再次捕獲到bid()方法中的異常,并對該異常進行處理print('main函數捕捉的異常:',ae)main()
上面程序中 9~13 行代碼對應的 except 塊捕獲到異常后,系統打印了該異常的字符串信息,接著引發一個 AuctionException 異常,通知該方法的調用者再次處理該 AuctionException 異常。所以程序中的 main() 函數,也就是 bid() 方法的調用者還可以再次捕獲 AuctionException 異常,井將該異常的詳細描述信息打印出來。
這種 except 和 raise 結合使用的情況在實際應用中非常常用。實際應用對異常的處理通常分成兩個部分:
應用后臺需要通過日志來記錄異常發生的詳細情況;
應用還需要根據異常向應用使用者傳達某種提示;
在這種情形下,所有異常都需要兩個方法共同完成,也就必須將 except 和 raise 結合使用。
如果程序需要將原始異常的詳細信息直接傳播出去,Python 也允許用自定義異常對原始異常進行包裝,只要將上面 ① 號代碼改為如下形式即可:
raiseAuctionException(e)
上面就是把原始異常 e 包裝成了 AuctionException 異常,這種方式也被稱為異常包裝或異常轉譯。
自定義異常類
很多時候,程序可選擇引發自定義異常,因為異常的類名通常也包含了該異常的有用信息。所以在引發異常時,應該選擇合適的異常類,從而可以明確地描述該異常情況。在這種情形下,應用程序常常需要引發自定義異常。
用戶自定義異常都應該繼承 Exception 基類或 Exception 的子類,在自定義異常類時基本不需要書寫更多的代碼,只要指定自定義異常類的父類即可。
下面程序創建了一個自定義異常類:
classAuctionException(Exception):pass
上面程序創建了 AuctionException 異常類,該異常類不需要類體定義,因此使用 pass 語句作為占位符即可。
在大部分情況下,創建自定義異常類都可采用與上面程序相似的代碼來完成,只需改變 AuctionException 異常的類名即可,讓該異常的類名可以準確地描述該異常。
關于python中出現raise異常是什么意思就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
@真智新坐標如果不是自己手機下單,但是知道快遞單號,如何快速查詢該號的物流軌跡?走了一段彎路還發現了一個很有用的APP。以前我們店主進貨的時候會把貨物的快遞單號發到微信上,這樣我們就可以隨時查看貨物的物流軌跡。發貨人使用的快遞公司經常更換。如果發貨人用的是大云快遞,我會先在網上搜索“大云快遞單號查詢”,然后輸入運單號,找到貨物的物流軌跡。如果發貨人用的是百世快遞,我會在網上輸入百世快遞單號進行查詢...
眾所周知,住房公積金貸款是非常劃算的,因為住房公積金貸款利率很低,但是仍然有不少人不喜歡欠銀行錢當房奴的感覺,一旦手中有了閑余的資金,就想要提前償還住房貸款,那么公積金可以提前還款嗎?怎樣用公積金還房貸?住房公積金貸款也是可以提前還款的,房貸用戶可以選擇提前部分還款,也可以選擇提前一次性全部結清;如果選擇提前部分還款,那么剩余未還款部分本金繼續按照原貸款合同計算利息,借款人選擇提前一次性全部結清,...
世界上最早的紙幣是什么?世界上最早的紙幣出現在哪個朝代?一起隨小編簡單了解下吧!世界上最早的紙幣是中國北宋時期四川成都的交子。北宋初年,銅錢流通很不方便,于是,商人發行一種紙幣,命名為交子,代替銅錢流通。紙幣比金屬貨幣容易攜帶,可以在較大范圍內使用,有利于商品的流通,促進了商品經濟的發展。最初的交子由商人自由發行,北宋初年,成都出現了專為攜帶巨款的商人經營現錢保管業務的“交子鋪戶&rd...