1. 程式人生 > >python中的異常處理常用方法

python中的異常處理常用方法

異常處理

  • 什麼是異常?

    異常就是與正常情況不同,程式在執行過程中出現錯誤,導致無法執行完畢。異常其實就是程式碼執行過程中出錯。

  • 常見的一些異常

    • AttributeError 試圖訪問一個物件沒有的屬性,比如foo.x,但是foo沒有屬性x

    • IOError 輸入/輸出異常;無法開啟檔案或無法讀寫

    • ImportError 無法引入模組或包;基本上是路徑問題或名稱錯誤

    • SyntaxError Python語法錯誤異常,程式碼不能編譯

    • IndentationError 縮排異常;程式碼沒有正確縮排

    • IndexError 下標索引超出序列邊界,比如當x只有三個元素,卻試圖訪問x[5]

    • KeyError 試圖訪問字典裡不存在的鍵

    • KeyboardInterrupt Ctrl+C被按下

    • NameError 使用一個還未被賦予物件的變數

    • TypeError 傳入物件型別與要求的不符合

    • UnboundLocalError 試圖訪問一個還未被設定的區域性變數,基本上是由於另有一個同名的全域性變數,
      導致你以為正在訪問它

    • ValueError 傳入一個呼叫者不期望的值,即使值的型別是正確的

 

  • 異常組成的三個部分

    追蹤資訊、異常型別、異常的值

 

異常可以由發生的時間不同分為兩類:

  1. 語法檢測異常:直譯器解釋python語法時出現異常。必須在程式執行前改正。

  2. 執行時異常:已經通過了語法檢測,在執行期間發生異常。(邏輯錯誤)

 

幾種不同的異常處理的語法

1.如果錯誤發生的條件是可以預知的,我們需要用if進行處理:在錯誤發生之前進行預防

AGE=10
while True:
    age=input('>>: ').strip()
    if age.isdigit(): #只有在age為字串形式的整數時,下列程式碼才不會出錯,該條件是可預知的
        age=int(age)
        if age == AGE:
            
print('you got it') break else: print('you are wrong') break else: print('請輸入數字~~')

 

2.如果發生的錯誤條件是不可以預知的,我們就需要用到try......except的幾種用法:

在錯誤發生之後進行處理。

  1. try.....except

    try:
    被檢測的程式碼塊
    except 異常型別:
    try中一旦檢測到異常,就執行這個位置的邏輯

    #這種方式只能用來處理指定的異常情況,如果非指定異常則無法處理。如果是非指定的異常型別會直接報錯。
    try:
        print('starting')
        a = int('deng')       # 這個位置很明顯是有邏輯錯誤的
        print('ending')       # 未執行這行程式碼
    except ValueError:        # 檢測到異常後執行了下面程式碼
        print('發生了ValueError') 
        
    ##
    starting
    發生了ValueError

     

  2. 多分枝

    try:
    被檢測的程式碼塊
    except 異常型別1:
    try中一旦檢測到異常,就執行這個位置的邏輯

    except 異常型別2:
    try中一旦檢測到異常,就執行這個位置的邏輯

    try:
        print('starting')
        l = []
        print(l[1])              #這個位置發生了IndexError
        int('deng')              #未執行
        print('ending')
    except ValueError:           #未執行
        print('發生了ValueError')
    except IndexError:           #檢測到異常,執行下面程式碼
        print('發生了IndexError')
    ###
    starting
    發生了IndexError

     

  3. 同一分支檢測多種異常

    try:

          被檢測的程式碼塊

    except(多種異常型別):

           try一旦檢測到異常,就執行這個位置的邏輯

    try:
        print('starting')
        l = []
        print(l[1])        #可以看出程式碼到這個位置就停止了
        print('ending')
        int('deng')
    except (ValueError,IndexError):   #只要檢測到異常就執行下面程式碼
        print('發生了ValueError')
    ###
    starting
    發生了ValueError

     

  4. 萬能異常1

    try:

    被檢測的程式碼塊

    except Exception:

    try一旦檢測到異常,就執行這個位置的邏輯

    #這種方式儘量不要用,會導致程式既不報錯,也不會正常執行,無法定位報錯位置。
    try:
        print('starting')
        l = []
        print(l[1])
        print('ending')
        int('deng')
    except Exception:
        print('going')

     

  5. 萬能異常2

    try:

    被檢測的程式碼塊

    except Exception as e:

    try一旦檢測到異常,就執行這個位置的邏輯

    try:
        print('starting')
        l = []
        print(l[1])
        print('ending')
        int('deng')
    except Exception as e:  #通過給異常取別名,來獲取異常物件,物件中包含錯誤資訊
        print('going')
        print(e)
        print(type(e))
    ###
    starting
    going
    list index out of range
    <class 'IndexError'>

     

    我們可以看到e是一個類,所有的異常類都是Exception的子類。

    萬能異常與多分枝異常處理區別。

    1.如果你想要的效果是,無論出現什麼異常,我們統一丟棄,或者使用同一段程式碼邏輯去處理他們,那麼騷年,大膽的去做吧,只有一個Exception就足夠了。
    2.如果你想要的效果是,對於不同的異常我們需要定製不同的處理邏輯,那就需要用到多分支了。

  6. 明確型別與萬能異常2合用

    try:
    被檢測的程式碼塊
    except 異常型別1:
    try中一旦檢測到異常,就執行這個位置的邏輯

    except 異常型別2:
    try中一旦檢測到異常,就執行這個位置的邏輯

    except Exception as e:

    try一旦檢測到異常,就執行這個位置的邏輯

    #明確型別應該放在萬能型別前才能正常使用
    try:
        print('starting')
        l = []
        print(l[1])
        print('ending')
        int('deng')
    except ValueError:            
        print('值發生錯誤。。。')
    except ZeroDivisionError:
        print('被除數不能為0')
    except Exception as e:
        print('going')

     

  7. try:
    被檢測的程式碼塊
    except 異常型別1:
    try中一旦檢測到異常,就執行這個位置的邏輯

    except 異常型別2:
    try中一旦檢測到異常,就執行這個位置的邏輯

    except Exception as e:

    try一旦檢測到異常,就執行這個位置的邏輯

    else:

    程式碼體中沒有異常執行這個位置的邏輯

    try:
        print('starting')
        l = []
        print(l[1])
        print('ending')
        int('deng')
    except ValueError:
        print('值發生錯誤。。。')
    except ZeroDivisionError:
        print('被除數不能為0')
    except Exception as e:
        print('going')
    else:
        print('這段程式碼沒有問題')

     

  8. try:
    被檢測的程式碼塊
    except 異常型別1:
    try中一旦檢測到異常,就執行這個位置的邏輯

    except 異常型別2:
    try中一旦檢測到異常,就執行這個位置的邏輯

    except Exception as e:

    try一旦檢測到異常,就執行這個位置的邏輯

    else:

    程式碼體中沒有異常執行這個位置的邏輯

    finally:

    程式碼體不管是否有異常,最終都執行該部分邏輯

    try:
        print('starting')
        l = []
        print(l[1])
        print('ending')
        int('deng')
    except ValueError:
        print('值發生錯誤。。。')
    except ZeroDivisionError:
        print('被除數不能為0')
    except Exception as e:
        print('going')
    else:
        print('這段程式碼沒有問題')
    finally:
        print('這是備用方案~~')
        print('這是關閉檔案操作')

     

  9. 主動觸發丟擲異常

    try:
    raise TypeError('型別錯誤')
    except Exception as e:
    print(e)

    #自定義異常
    class LoginException(Exception):
        passdef login():
        name = input('name>>:').strip()
        pwd = input('password>>:').strip()
        if name == 'deng' and pwd == '123':
            print('login')
        else:
            raise LoginException('使用者名稱密碼錯誤!~')
    ​
    login()

     

  10. 斷言 assert

    在程式中,有一段程式碼體,要執行必須保證某個條件必須成立,類似於if判斷,但是斷言不用將程式碼體縮排至其內部。

    #使用if判斷
    l = ['ming','deng']
    if l:
        print('nihaoa ')
    #使用斷言    
    assert l
    print('nihaom')
    print(l[0])

     

 

總結:異常處理的作用

1:把錯誤處理和真正的工作分開來
2:程式碼更易組織,更清晰,複雜的工作任務更容易實現;
3:毫無疑問,更安全了,不至於由於一些小的疏忽而使程式意外崩潰了。