Python的異常處理機制

程式在執行時難免會因為各種“意外因素”或程式本身的邏輯問題導致出錯,嚴重時這將使程式徹底崩潰。解決這些問題常規的思路就是增加大量的邏輯判斷語句來消滅種種可能引起問題的“意外因素”,但這無疑會使程式程式碼變得複雜而龐大,並且十分脆弱。有沒有更好的解決辦法呢?如果沒有的話也不會有你看到的這篇文章了,哈哈哈~

可以在錯誤(Python中稱之為“異常”)產生時捕獲異常,並按照給定的異常恢復程式碼嘗試恢復異常。當然,如果你不捕獲異常,那麼當異常發生時,程式就必死無疑了。

先來看一個小程式。

給出一個文字檔案“file.txt”,檔案內容如下所示。要求:利用Python字串的split()方法來分別獲取每行字串中”:”兩邊的字元,以第一行字串為例,要求最終輸出為此形式:aa said: aaa

aa:aaa
bb:bbb
(ccc)
dd:ddd
ee:eee
ff:fff:fff

編寫程式如下。

file_data = open('file.txt','r',encoding='UTF-8')        #開啟"file.txt"檔案
for i in file_data:                 #利用for迴圈迭代讀取"file.txt"檔案的內容
    (a,b) = i.split(':',1)          #利用字串的split()方法,以":"為切割條件(只切割一次),對每行字串進行分割操作,最後將生成的列表中的兩個元素分別賦值給變數a、b。
    print(a,end = '')               #輸出變數a
    print(' said: ',end = '')       #輸出字串" said "
    print(b,end = '')               #輸出變數b
file_data.close()                   #關閉檔案

看似程式的邏輯上是沒有問題的,但是執行後會發現Python的直譯器丟擲瞭如下異常。

aa said: aaa               #按照程式中預設的邏輯正確輸出了處理後的字串
bb said: bbb               #正確輸出
Traceback (most recent call last):      #丟擲了一個Traceback型別的異常!!!
 File "./a.py", line 5, in <module>
 (aa,bb) = i.split(':',1)
ValueError: not enough values to unpack (expected 2, got 1)

上面的異常的內容大致是:沒有足夠的值來賦給變數,應該有兩個值,但現在只有一個。

檢視”file.txt”檔案的內容,可以發現,第三行的內容是:

(ccc)

這個字串中沒有包含“:”,理所當然的,split()方法並沒有將其切割為列表的兩個元素,所以在賦值時就產生了錯誤。

解決這個錯誤可以用邏輯判斷語句來針對特定的場景給出特定的解決方法(預防異常產生),如下:

file_data = open('file','r',encoding='UTF-8')
for i in file_data:
    if not i.find(':') == -1:        #增加一個判斷,只有當字串中包含“:”字元時才執行相關語句。
        (aa,bb) = i.split(':',1)
        print(a,end = '')
        print(' said: ',end = '')
        print(b,end = '')
file_data.close()

這種方法雖然能解決問題,但需要對每一種可能出現的錯誤情況給出特定的邏輯判斷語句及其他程式程式碼才能避免異常,這樣做的弊端是顯而易見的,畢竟且不論編寫這樣的程式碼有多麼繁瑣,光是考慮日後維護程式碼的工作量就已經令人窒息。

下面來看另一種解決方法:利用異常處理來解決此問題(允許異常產生,但會捕獲異常並進行修復)。

file_data = open('file','r',encoding='UTF-8')
for i in file_data:
    try:             #捕獲異常
        (a,b) = i.split(':',1)
        print(a,end = '')
        print(' said: ',end = '')
        print(b,end = '')
    except:          #給出修復異常的程式程式碼
        continue     #跳過本次迴圈
file_data.close()

程式正確執行並給出如下輸出:

aa said: aaa
bb said: bbb
dd said: ddd
ee said: eee
ff said: fff:fff

異常處理的工作原理就是像文章開頭說的那樣,捕獲一個異常,然後按照給定的恢復的程式碼來嘗試恢復異常,就這麼簡單。

上邊的例子中,我們捕獲了全部的異常,並對所有的異常應用了同一段恢復程式碼,那該如何針對某一型別的異常執行某一特定的恢復程式碼呢?

可以這樣寫,這裡只對IOError型別的錯誤應用恢復程式碼:

try :
    ...
except IOError:
    ...

以上介紹的就是Python的異常處理機制是簡單用法,異常處理的好處就是可以讓你能更加專注實現程式本身的功能,而不必費時費力的預先考慮各種可能產生的錯誤並寫出預防錯誤的相應的邏輯判斷及額外程式碼。