當程序出現錯誤時,系統會自動引起異常。除此以外,Python也容許程序自行引起異常,自行引起異常使用 raise 語句來完成。程序員
不少時候,系統是否要引起異常,可能須要根據應用的業務需求來決定,若是程序中的數據、執行與既定的業務需求不符,這就是一種異常。因爲與業務需求不符而產生的異常,必須由程序員來決定引起,系統沒法引起這種異常。app
若是須要在程序中自行引起異常,則應使用 raise 語句。raise 語句有以下三種經常使用的用法:ide
raise:單獨一個 raise。該語句引起當前上下文中捕獲的異常(好比在 except 塊中),或默認引起 RuntimeError 異常。函數
raise 異常類:raise 後帶一個異常類。該語句引起指定異常類的默認實例。學習
raise 異常對象:引起指定的異常對象。spa
上面三種用法最終都是要引起一個異常實例(即便指定的是異常類,實際上也是引起該類的默認實例),raise 語句每次只能引起一個異常實例。日誌
能夠利用 raise 語句再次改寫前面五子棋遊戲中處理用戶輸入的代碼:對象
try : #將用戶輸入的字符串以逗號( ,)做爲分隔符,分隔成兩個字符串 x_str, y_str = inputStr.split(sep =",") #若是要下棋的點不爲空 if board[int(y_str) - 1] [int(x_str) - 1] != "+": #引起默認的RuntimeError異常 raise #把對應的列表元素賦爲」●」 board [int(y_str) - 1] [int(x_str) - 1] = 」●」except Exception as e: print (type(e)) inputStr = input("您輸入的座標不合法,請從新輸入,下棋座標應以x,y 的格式\n") continue
上面程序中第 7 行代碼使用 raise 語句來自行引起異常,程序認爲當用戶試圖向一個已有棋子的座標點下棋時就是異常。當 Python 解釋器接收到開發者自行引起的異常時,一樣會停止當前的執行流,跳到該異常對應的 except 塊,由該 except 塊來處理該異常。也就是說,不論是系統自動引起的異常,仍是程序員於動引起的異常,Python 解釋器對異常的處理沒有任何差異。繼承
即便是用戶自行引起的異常,也可使用 try except 來捕獲它。固然也能夠無論它,讓該異常向上(先調用者)傳播,若是該異常傳到 Python 解釋器,那麼程序就會停止。遊戲
下面示例示範了處理用戶引起異常的兩種方式:
def main(): try: # 使用try...except來捕捉異常 # 此時即便程序出現異常,也不會傳播給main函數 mtd(3) except Exception as e: print('程序出現異常:', e) # 不使用try...except捕捉異常,異常會傳播出來致使程序停止 mtd(3)def mtd(a): if a > 0: raise ValueError("a的值大於0,不符合要求")main()
從上面程序能夠看到,程序既可在調用 mtd(3) 時使用 try except 來捕獲異常,這樣該異常將會被 except 塊捕獲,不會傳播給調用它的函數;也可直接調用 mtd(3),這樣該函數的異常就會直接傳播給它的調用函數,若是該函數也不處理該異常,就會致使程序停止。
運行上面程序,能夠看到以下輸出結果:
程序出現異常: 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,不符合要求
上面第一行輸出是第一次調用 mtd (3) 的結果,該方法引起的異常被 except 塊捕獲並處理。後面的大段輸出則是第二次調用 mtd(3) 的結果,因爲該異常沒有被 except 塊捕獲,所以該異常一直向上傳播,直到傳給 Python 解釋器致使程序停止。
第二次調用 mtd(3) 引起的以「File」開頭的三行輸出,其實顯示的就是異常的傳播軌跡信息。也就是說,若是程序不對異常進行處理,Python 默認會在控制檯輸出異常的傳播軌跡信息。
自定義異常類
不少時候,程序可選擇引起自定義異常,由於異常的類名一般也包含了該異常的有用信息。因此在引起異常時,應該選擇合適的異常類,從而能夠明確地描述該異常狀況。在這種情形下,應用程序經常須要引起自定義異常。
用戶自定義異常都應該繼承 Exception 基類或 Exception 的子類,在自定義異常類時基本不須要書寫更多的代碼,只要指定自定義異常類的父類便可。
下面程序建立了一個自定義異常類(程序一):
class AuctionException(Exception): pass
上面程序建立了 AuctionException 異常類,該異常類不須要類體定義,所以使用 pass 語句做爲佔位符便可。
在大部分狀況下,建立自定義異常類均可採用與程序一類似的代碼來完成,只需改變 AuctionException 異常的類名便可,讓該異常的類名能夠準確地描述該異常。
except 和 raise 同時使用
在實際應用中對異常可能須要更復雜的處理方式。當一個異常出現時,單靠某個方法沒法徹底處理該異常,必須由幾個方法協做纔可徹底處理該異常。也就是說,在異常出現的當前方法中,程序只對異常進行部分處理,還有些處理須要在該方法的調用者中才能完成,因此應該再次引起異常,讓該方法的調用者也能捕獲到異常。
爲了實現這種經過多個方法協做處理同一個異常的情形,能夠在 except 塊中結合 raise 語句來完成。以下程序示範了except 和 raise 同時使用的方法:
class AuctionException(Exception): passclass 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("轉換出異常:", e) # 再次引起自定義異常 raise AuctionException("競拍價必須是數值,不能包含其餘字符!") # ① raise AuctionException(e) if self.init_price > d: raise AuctionException("競拍價比起拍價低,不容許競拍!") initPrice = ddef main(): at = AuctionTest(20.4) try: at.bid("df") except AuctionException as ae: # 再次捕獲到bid()方法中的異常,並對該異常進行處理 print('main函數捕捉的異常:', ae)main()
上面程序中 9~13 行代碼對應的 except 塊捕獲到異常後,系統打印了該異常的字符串信息,接着引起一個 AuctionException 異常,通知該方法的調用者再次處理該 AuctionException 異常。因此程序中的 main() 函數,也就是 bid() 方法的調用者還能夠再次捕獲 AuctionException 異常,井將該異常的詳細描述信息打印出來。
這種 except 和 raise 結合使用的狀況在實際應用中很是經常使用。實際應用對異常的處理一般分紅兩個部分:
應用後臺須要經過日誌來記錄異常發生的詳細狀況;
應用還須要根據異常向應用使用者傳達某種提示;
在這種情形下,全部異常都須要兩個方法共同完成,也就必須將 except 和 raise 結合使用。
若是程序須要將原始異常的詳細信息直接傳播出去,Python 也容許用自定義異常對原始異常進行包裝,只要將上面 ① 號代碼改成以下形式便可:
raise AuctionException(e)
raise 不須要參數
正如前面所看到的,在使用 raise 語句時能夠不帶參數,此時 raise 語句處於 except 塊中,它將會自動引起當前上下文激活的異常;不然,一般默認引起 RuntimeError 異常。
例如,將上面程序改成以下形式:
class AuctionException(Exception): passclass 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("轉換出異常:", e) # 再次引起自定義異常 raise if self.init_price > d: raise AuctionException("競拍價比起拍價低,不容許競拍!") initPrice = ddef main(): at = AuctionTest(20.4) try: at.bid("df") except AuctionException as ae: # 再次捕獲到bid()方法中的異常,並對該異常進行處理 print('main函數捕捉的異常:', ae)main()
正如從 13 行代碼所看到的,此時程序在 except 塊中只是簡單地使用 raise 語句來引起異常,那麼該 raise 語句將會再次引起該 except 塊所捕獲的異常。運行該程序,能夠看到以下輸出結果:
轉換出異常: could not convert string to float: 'df' main 函數捕獲的異常:<class 'ValueError'>
知識點補充:
演示raise用法
try: s = None if s is None: print "s 是空對象" raise NameError #若是引起NameError異常,後面的代碼將不能執行 print len(s) #這句不會執行,可是後面的except仍是會走到except TypeError: print "空對象沒有長度" s = Noneif s is None: raise NameError print 'is here?' #若是不使用try......except這種形式,那麼直接拋出異常,不會執行到這裏
觸發異常
咱們可使用raise語句本身觸發異常
raise語法格式以下:
raise [Exception [, args [, traceback]]]
語句中 Exception 是異常的類型(例如,NameError)參數標準異常中任一種,args 是自已提供的異常參數。
最後一個參數是可選的(在實踐中不多使用),若是存在,是跟蹤異常對象。到此這篇關於Python新手學習raise用法的文章就介紹到這了,更多相關Python中raise用法內容請搜索之前的文章或繼續瀏覽下面的相關文章但願你們之後多多支持!