溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python有哪些raise用法

發(fā)布時(shí)間:2020-08-25 16:48:40 來源:億速云 閱讀:251 作者:Leah 欄目:編程語言

本篇文章給大家分享的是有關(guān)Python有哪些raise用法,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

當(dāng)程序出現(xiàn)錯(cuò)誤時(shí),系統(tǒng)會自動引發(fā)異常。除此之外,Python 也允許程序自行引發(fā)異常,自行引發(fā)異常使用 raise 語句來完成。

很多時(shí)候,系統(tǒng)是否要引發(fā)異常,可能需要根據(jù)應(yīng)用的業(yè)務(wù)需求來決定,如果程序中的數(shù)據(jù)、執(zhí)行與既定的業(yè)務(wù)需求不符,這就是一種異常。由于與業(yè)務(wù)需求不符而產(chǎn)生的異常,必須由程序員來決定引發(fā),系統(tǒng)無法引發(fā)這種異常。

如果需要在程序中自行引發(fā)異常,則應(yīng)使用 raise 語句。raise 語句有如下三種常用的用法:

raise:單獨(dú)一個(gè) raise。該語句引發(fā)當(dāng)前上下文中捕獲的異常(比如在 except 塊中),或默認(rèn)引發(fā) RuntimeError 異常。

raise 異常類:raise 后帶一個(gè)異常類。該語句引發(fā)指定異常類的默認(rèn)實(shí)例。

raise 異常對象:引發(fā)指定的異常對象。

上面三種用法最終都是要引發(fā)一個(gè)異常實(shí)例(即使指定的是異常類,實(shí)際上也是引發(fā)該類的默認(rèn)實(shí)例),raise 語句每次只能引發(fā)一個(gè)異常實(shí)例。

可以利用 raise 語句再次改寫前面五子棋游戲中處理用戶輸入的代碼:

try :
    #將用戶輸入的字符串以逗號( ,)作為分隔符,分隔成兩個(gè)字符串
    x_str, y_str = inputStr.split(sep =",")
    #如果要下棋的點(diǎn)不為空
    if board[int(y_str) - 1] [int(x_str) - 1] != "+":
    #引發(fā)默認(rèn)的RuntimeError異常
    raise
    #把對應(yīng)的列表元素賦為”●”
    board [int(y_str) - 1] [int(x_str) - 1] = ”●”
except Exception as e:
    print (type(e))
    inputStr = input("您輸入的坐標(biāo)不合法,請重新輸入,下棋坐標(biāo)應(yīng)以x,y 的格式\n")
    continue

上面程序中第 7 行代碼使用 raise 語句來自行引發(fā)異常,程序認(rèn)為當(dāng)用戶試圖向一個(gè)已有棋子的坐標(biāo)點(diǎn)下棋時(shí)就是異常。當(dāng) Python 解釋器接收到開發(fā)者自行引發(fā)的異常時(shí),同樣會中止當(dāng)前的執(zhí)行流,跳到該異常對應(yīng)的 except 塊,由該 except 塊來處理該異常。也就是說,不管是系統(tǒng)自動引發(fā)的異常,還是程序員于動引發(fā)的異常,Python 解釋器對異常的處理沒有任何差別。

即使是用戶自行引發(fā)的異常,也可以使用 try except 來捕獲它。當(dāng)然也可以不管它,讓該異常向上(先調(diào)用者)傳播,如果該異常傳到 Python 解釋器,那么程序就會中止。

下面示例示范了處理用戶引發(fā)異常的兩種方式:

def main():
    try:
        # 使用try...except來捕捉異常
        # 此時(shí)即使程序出現(xiàn)異常,也不會傳播給main函數(shù)
        mtd(3)
    except Exception as e:
        print('程序出現(xiàn)異常:', e)
    # 不使用try...except捕捉異常,異常會傳播出來導(dǎo)致程序中止
    mtd(3)
def mtd(a):
    if a > 0:
        raise ValueError("a的值大于0,不符合要求")
main()

從上面程序可以看到,程序既可在調(diào)用 mtd(3) 時(shí)使用 try except 來捕獲異常,這樣該異常將會被 except 塊捕獲,不會傳播給調(diào)用它的函數(shù);也可直接調(diào)用 mtd(3),這樣該函數(shù)的異常就會直接傳播給它的調(diào)用函數(shù),如果該函數(shù)也不處理該異常,就會導(dǎo)致程序中止。

運(yùn)行上面程序,可以看到如下輸出結(jié)果:

程序出現(xiàn)異常: a的值大于0,不符合要求
Traceback (most recent call last):
  File "C:\Users\mengma\Desktop\1.py", line 13, in <module>
    main()
  File "C:\Users\mengma\Desktop\1.py", line 9, in main
    mtd(3)
  File "C:\Users\mengma\Desktop\1.py", line 12, in mtd
    raise ValueError("a的值大于0,不符合要求")
ValueError: a的值大于0,不符合要求

上面第一行輸出是第一次調(diào)用 mtd (3) 的結(jié)果,該方法引發(fā)的異常被 except 塊捕獲并處理。后面的大段輸出則是第二次調(diào)用 mtd(3) 的結(jié)果,由于該異常沒有被 except 塊捕獲,因此該異常一直向上傳播,直到傳給 Python 解釋器導(dǎo)致程序中止。

第二次調(diào)用 mtd(3) 引發(fā)的以“File”開頭的三行輸出,其實(shí)顯示的就是異常的傳播軌跡信息。也就是說,如果程序不對異常進(jìn)行處理,Python 默認(rèn)會在控制臺輸出異常的傳播軌跡信息。

自定義異常類

很多時(shí)候,程序可選擇引發(fā)自定義異常,因?yàn)楫惓5念惷ǔR舶嗽摦惓5挠杏眯畔?。所以在引發(fā)異常時(shí),應(yīng)該選擇合適的異常類,從而可以明確地描述該異常情況。在這種情形下,應(yīng)用程序常常需要引發(fā)自定義異常。

用戶自定義異常都應(yīng)該繼承 Exception 基類或 Exception 的子類,在自定義異常類時(shí)基本不需要書寫更多的代碼,只要指定自定義異常類的父類即可。

下面程序創(chuàng)建了一個(gè)自定義異常類(程序一):

class AuctionException(Exception): pass

上面程序創(chuàng)建了 AuctionException 異常類,該異常類不需要類體定義,因此使用 pass 語句作為占位符即可。

在大部分情況下,創(chuàng)建自定義異常類都可采用與程序一相似的代碼來完成,只需改變 AuctionException 異常的類名即可,讓該異常的類名可以準(zhǔn)確地描述該異常。

except 和 raise 同時(shí)使用

在實(shí)際應(yīng)用中對異??赡苄枰鼜?fù)雜的處理方式。當(dāng)一個(gè)異常出現(xiàn)時(shí),單靠某個(gè)方法無法完全處理該異常,必須由幾個(gè)方法協(xié)作才可完全處理該異常。也就是說,在異常出現(xiàn)的當(dāng)前方法中,程序只對異常進(jìn)行部分處理,還有些處理需要在該方法的調(diào)用者中才能完成,所以應(yīng)該再次引發(fā)異常,讓該方法的調(diào)用者也能捕獲到異常。

為了實(shí)現(xiàn)這種通過多個(gè)方法協(xié)作處理同一個(gè)異常的情形,可以在 except 塊中結(jié)合 raise 語句來完成。如下程序示范了except 和 raise 同時(shí)使用的方法:

class AuctionException(Exception): pass
class AuctionTest:
    def __init__(self, init_price):
        self.init_price = init_price
    def bid(self, bid_price):
        d = 0.0
        try:
            d = float(bid_price)
        except Exception as e:
            # 此處只是簡單地打印異常信息
            print("轉(zhuǎn)換出異常:", e)
            # 再次引發(fā)自定義異常
            raise AuctionException("競拍價(jià)必須是數(shù)值,不能包含其他字符!")  # ①
            raise AuctionException(e)
        if self.init_price > d:
            raise AuctionException("競拍價(jià)比起拍價(jià)低,不允許競拍!")
        initPrice = d
def main():
    at = AuctionTest(20.4)
    try:
        at.bid("df")
    except AuctionException as ae:
        # 再次捕獲到bid()方法中的異常,并對該異常進(jìn)行處理
        print('main函數(shù)捕捉的異常:', ae)
main()

上面程序中 9~13 行代碼對應(yīng)的 except 塊捕獲到異常后,系統(tǒng)打印了該異常的字符串信息,接著引發(fā)一個(gè) AuctionException 異常,通知該方法的調(diào)用者再次處理該 AuctionException 異常。所以程序中的 main() 函數(shù),也就是 bid() 方法的調(diào)用者還可以再次捕獲 AuctionException 異常,井將該異常的詳細(xì)描述信息打印出來。

這種 except 和 raise 結(jié)合使用的情況在實(shí)際應(yīng)用中非常常用。實(shí)際應(yīng)用對異常的處理通常分成兩個(gè)部分:

應(yīng)用后臺需要通過日志來記錄異常發(fā)生的詳細(xì)情況;

應(yīng)用還需要根據(jù)異常向應(yīng)用使用者傳達(dá)某種提示;

在這種情形下,所有異常都需要兩個(gè)方法共同完成,也就必須將 except 和 raise 結(jié)合使用。

如果程序需要將原始異常的詳細(xì)信息直接傳播出去,Python 也允許用自定義異常對原始異常進(jìn)行包裝,只要將上面 ① 號代碼改為如下形式即可:

raise AuctionException(e)

raise 不需要參數(shù)

正如前面所看到的,在使用 raise 語句時(shí)可以不帶參數(shù),此時(shí) raise 語句處于 except 塊中,它將會自動引發(fā)當(dāng)前上下文激活的異常;否則,通常默認(rèn)引發(fā) RuntimeError 異常。

例如,將上面程序改為如下形式:

class AuctionException(Exception): pass
class AuctionTest:
    def __init__(self, init_price):
        self.init_price = init_price
    def bid(self, bid_price):
        d = 0.0
        try:
            d = float(bid_price)
        except Exception as e:
            # 此處只是簡單地打印異常信息
            print("轉(zhuǎn)換出異常:", e)
            # 再次引發(fā)自定義異常
            raise
        if self.init_price > d:
            raise AuctionException("競拍價(jià)比起拍價(jià)低,不允許競拍!")
        initPrice = d
def main():
    at = AuctionTest(20.4)
    try:
        at.bid("df")
    except AuctionException as ae:
        # 再次捕獲到bid()方法中的異常,并對該異常進(jìn)行處理
        print('main函數(shù)捕捉的異常:', ae)
main()

正如從 13 行代碼所看到的,此時(shí)程序在 except 塊中只是簡單地使用 raise 語句來引發(fā)異常,那么該 raise 語句將會再次引發(fā)該 except 塊所捕獲的異常。運(yùn)行該程序,可以看到如下輸出結(jié)果:

轉(zhuǎn)換出異常: could not convert string to float: 'df'
main 函數(shù)捕獲的異常:<class 'ValueError'>

從輸出結(jié)果來看,此時(shí) main() 函數(shù)再次捕獲了 ValueError,它就是在 bid() 方法中 except 塊所捕獲的原始異常。


以上就是Python有哪些raise用法,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI