Python基础(九)--异常
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Python基礎(九)--異常
1 異常相關概念
1.1 什么是異常
異常是程序運行過程中產生的一種事件,該事件會打亂程序的正常流程??梢哉f,異常就是一種意外,指程序沒有按照正?;蚱谕姆绞綀绦?。
當異常產生時,會創建一個相關異常類的對象,該對象含有異常的相關信息。異常產生時,會在異常的上下文中尋找異常處理程序,如果沒有異常處理程序,則異常產生之后的語句將不會得到執行。該異常會向上傳播。傳播的方式為:
①如果異常是在函數中產生的,則傳播給函數的調用者
②如果異常是在模塊頂級位置產生的,則傳播給導入該模塊的另一個模塊
如果當前模塊作為腳本運行,則異常會傳播給解釋器,如果到了解釋器,異常還未解決,則當前線程會終止執行。離異常產生越近的信息,會在越下面顯示,因此分析異常時,應該從下往上看。
def A():B() def B():C() def C():a = 6 / 0 A()1.2 常見異常類型
異常命名慣例,以Error結尾。
| 異常類型 | 描述 |
| BaseException | Python中所有異常的根類 |
| Exception | BaseException的子類,用戶異常的根類 |
| ZeroDivisionError | 當除數為0時,產生的異常 |
| AssertionError | 斷言的異常,當斷言條件不滿足時產生 |
| ModuleNotFoundError | 當使用import導入的模塊不存在時產生的異常 |
| IndexError | 索引異常,當索引越界時產生 |
| KeyError | 鍵訪問異常,當鍵不存在時會產生 |
| NameError | 名稱異常,當訪問名稱不存在時產生 |
| RecursionError | 遞歸異常,當函數調用層次達到最大層次限制時產生 |
| StopIteration | 迭代終止異常,當迭代器已經沒有元素是產生 |
| SyntaxError | 語法錯誤異常,編寫的代碼不符合語法規定時產生 |
| ValueError | 值異常,當對值處理錯誤是產生 |
2 捕獲異常
2.1 try...except
在Python中,可以使用try-except的語法來捕獲異常,我們可以將其稱為異常處理程序。格式如下:
try:可能產生異常的程序except 異常類型1:恢復措施except 異常類型2:恢復措施……except 異常類型n:恢復措施其中,try用來執行可能會產生異常的程序,而except用來捕獲try中產生的異常,用來執行一些恢復或補救操作,或者給出錯誤的提示信息等。這分為三種情況:
①try語句塊沒有產生異常。
此時try語句塊全部執行完畢,不會執行任何except分支(因為沒有異常),然后繼續執行try-except之后的語句。
②try語句塊中產生異常,except捕獲了該異常。
會創建相關異常類型的對象,try異常之后的語句不會得到執行(不論except能否捕獲該異常)。然后對該異常對象與各個exception分支不會的異常類型進行匹配。匹配的原則為:isinstance(異常對象,except捕獲的異常類型),如果匹配成功,則執行對應的except分支,匹配順序從上到下。如果能夠匹配成功,表示成功捕獲異常,try-except之后的語句可以正常執行。
③try語句塊中產生異常,但是except沒有捕獲該異常。
如果try中產生異常,但是except沒有捕獲該異常,則該異常繼續存在,try-except之后的語句不會得到執行。該異常向上傳播
捕獲異常對象:可以使用except捕獲異常,同時,我們也能夠使用as語法獲取try中產生的異常對象。語法格式為:
try:可能產生異常的代碼 except 異常類型 as 變量:處理異常代碼當異常匹配成功時,我們就會將try中產生的異常對象賦值給as變量名,然后,我們就可以在except中使用變量名來訪問異常對象了。
try:print(5 / 0) except ZeroDivisionError as e:# 通過異常對象的args屬性獲取異常對象構造器的參數。print(e.args)異常對象的args屬性返回一個元組類型,其中存放異常對象創建時,傳遞給構造器中的參數值。
?
2.2 捕獲多個一次
因為在try語句塊中,可能產生不止一種異常,故我們會使用多個except分支來捕獲這些可能產生的異常。如果多個異常類之間沒有繼承關系時,except分支的順序不是十分重要,但是,當異常類之間存在異常關系時,就一定要將子類放在前面,父類放在后面。因為子類異常對象也是父類異常類的實例,如果將父類分支放在子類分支之前,則就算try中產生子類異常,也會先由父類分支率先捕獲,子類分支永遠都沒有機會執行,這就失去了意義。所以,在捕獲異常時,except分支應該按照從特殊性(子類)到一般性(父類)的方式排序。
except還有一種語法,就是不指定異常類型,此時表示捕獲所有異常類型。因為捕獲所有的異常類型是最廣泛的(最具有一般性),所以,如果使用這種方式,則必須將該except置于最后(作為最后一條except分支)。例如:
try:可能產生異常的代碼 except: # 沒有指定異常類型,會捕獲所有的異常。pass?
同時捕獲多個異常:當try中產生了兩種(或更多)的異常,而多種異常的處理方式又完全相同時,我們使用多條except分支,會造成代碼的重復。此時,我們可以使用一條except分支,同時捕獲多個異常來代替。
try:# 操作 except (IndexError, KeyError):print("提供值不合法,獲取失敗!")這樣,無論try中產生IndexError還是KeyError,except分支都可以進行捕獲。也許大家會有這樣的想法,這種捕獲多個異常有什么用呢,使用不指定異常類型的except豈不是更好,能捕獲所有異常,可謂“萬事通用”。
try:# 操作except:print("提供值不合法,獲取失敗!")但是,如果這樣做,就很可能會捕獲預期之外的異常,從而掩埋真正的問題,令錯誤不易排查。因此,如果能夠捕獲更加具體明確的異常類型,我們最好不要使用更加通用一般的異常類型代替。
2.3 else
try-except還可以跟隨可選的else語句。語法為:
try:…… except 異常類型:…… else:……當try中沒有產生異常時,就會執行else分支,否則,不執行else分支。似乎感覺,else分支并沒有什么作用,完全可以將else分支放在try語句塊的后面啊,因為如果產生異常,try中異常之后的語句也不會執行。如果從程序(計算機)的角度講,確實可以這樣進行修改,然而,如果從程序員的角度講,else還是具有一定的意義的。因為,其可以將“可能產生異常的代碼”與“不產生異常后執行的代碼”進行有效的分離,從而讓程序更加清晰,具有可讀性。
else語句的作用:try中的語句應該是可能產生異常的語句,對于不會產生異常的語句,我們就不適合放在try中。else就可以將try中不產生異常的語句從try中分離,令程序結構變得更加清晰。
2.4 finally
try-except還可以帶上一個可選的finally。如果同時存在else,則finally必須處于else的后面,其實,except,else,與finally都是可選的。但是,except與finally二者不能同時缺失,即二者至少要存在一個。
finally會在try-except-else之后得到執行(如果存在except或else的話),且一定會得到執行。即無論try是否產生異常,也無論except是否捕獲try中產生的異常,finally終將會得到執行。
考慮到finally總是可以執行的特征,我們往往會在finally中執行一些清理的工作。例如,我們在try中申請了一些系統資源(文件讀寫,數據庫連接等),就可以在finally中進行資源釋放,從而不會造成資源泄露(資源申請,但沒有釋放)。如果將釋放語句寫在try中,則一旦在釋放之前產生異常,則資源釋放語句就不會得到執行。
# 在try和finally中同時又return時,finally中的return會鎮壓掉try中的 def fun():try:return 1finally:return 2 print(fun()) # 當try語句體中嘗試返回一個變量時,如果在finally中去修改該變量的值, # 不會影響到返回值的結果(返回的還是修改之前的值) def fun2():a = 1try:return afinally:a = 2 print(fun2()) # 驗證finally是否總會執行 # 1在循環中,通過break嘗試跳過finally語句塊 for i in range(10):try:breakfinally:print("finally總會執行") # 2、在方法中,執行return嘗試跳過finally語句塊。 def f():try:returnfinally:print("finally總會執行") f() # 3、調用sys模塊的exit方法,嘗試跳過finally語句塊 import sys try:sys.exit() finally:print("finally總會執行")3 拋出異常
在不符合要求時,可以主動產生一個異常,這樣就能夠給客戶端一個有效的提醒。我們可以創建一個異常對象,使用raise拋出,語法為:
raise 異常類或異常對象
例如:raise Exception("產生異常")
raise Exception
raise后面跟隨異常類,則相當于是調用其無參的構造器,因此,后者相當于:
raise Exception()
raise后面必須是一個有效的異常類(BaseException類型或其子類型)或對應異常類的對象,如果是其他類型,將會產生錯誤。
4 自定義異常
自定義異常通常繼承Exception類型(或其子類型),按照慣例,異常類以Error結尾。
為什么需要自定義:①Python提供的異常類型不能滿足所有的用戶,所有場景的需要。②自定義異常可以與Python系統提供的異常類型分開,有利于定位并解決問題
?
總結
以上是生活随笔為你收集整理的Python基础(九)--异常的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java子类继承父类实际_java子类继
- 下一篇: websocket python爬虫_p