Python之異常處理

轉自:白月黑羽Python3教程之異常處理:http://www.python3.vip/doc/tutorial/python/0019/python

異常對象

請你們運行以下代碼git

a = 100/0
print(a)

  

就會發現解釋器顯示以下的錯誤提示函數

Traceback (most recent call last):
  File "xxxxxxxxxx.py", line 1, in <module>
    a = 100/0
ZeroDivisionError: division by zero

  

你們要學會看解釋器的報錯。編碼

這就是解釋器向咱們報告, 有一個 ZeroDivisionError 錯誤對象 或者說 異常對象 產生了。spa

這個 ZeroDivisionError 對象 表明的是一個除以0 的異常。 咱們知道0是不能做爲除數的。命令行

由於這個問題,解釋器沒有辦法繼續執行後面的代碼了。因此程序就此結束執行了。線程

ZeroDivisionError就是一個異常對象的類,繼承自標準庫裏面的 Exception 類。code

Python標準庫中還有不少其餘的異常類 都是繼承自標準庫裏面的 Exception 類,表明各類不一樣類型的錯誤。orm

你們能夠在命令行窗口 運行 Python 解釋器交互命令行,分別輸入以下代碼:對象

xxxx 

會產生 NameError,表示xxxx沒有定義

dict1 = {1:1}
print(dict1[2])

  

會產生 KeyError,表示該字典沒有key爲2的元素

import xxxx

  

會產生 ModuleNotFoundError,表示找不到xxxx這樣的模塊

 

捕獲異常

解釋器執行代碼過程當中,若是發生異常,就會致使解釋器無法繼續按照正常流程往下執行代碼,因此解釋器會結束當前線程的執行。

若是執行的程序是個單線程的程序,整個程序執行就會結束了。

若是咱們在編碼的時候,就預料到了某些代碼運行時可能出現某些異常,就能夠使用 try...except... 這樣的方法來捕獲和處理異常。

好比,咱們要開發程序,實現一個把用戶輸入的身高從英尺換算成米,以下所示

while True:
    miles = input('請輸入英里數:')
    km = int(miles) * 1.609344
    print(f'等於{km}千米')

  

編寫這段代碼的時候, 咱們就能夠預料到,可能用戶會輸入非數字的字符,用int轉化就會出錯了,致使整個程序就退出了。

這時,咱們就能夠這樣寫

while True:
    try:
        miles = input('請輸入英里數:')
        km = int(miles) * 1.609344
        print(f'等於{km}千米')
    except ValueError:
        print('你輸入了非數字字符')

  

try 下面縮進的代碼出現異常時,解釋器會結束 try中 後續代碼的執行,並檢查這個異常的類型是否匹配後面的except 語句中聲明的類型。

若是匹配上,就認爲該異常是預先有對應的處理方案的,就執行匹配的except下面縮進的代碼。從而不會結束當前線程。

 

上面的例子中,執行 try 下面縮進的代碼時,若是用戶輸入了 hello 這樣的非數字, 就會在這行語句處

km = int(miles) * 1.609344

  

產生 ValueError 類型的異常, 解釋器就會去查看後面的 except 語句是否聲明瞭對 ValueError 異常的處理。

發現有, 就會執行後面縮進的代碼。也就是這句代碼

print('你輸入了非數字字符') 

except 後面縮進的代碼 就是對這種類型錯誤 的一種處理

既然程序已經知道如何處理這種問題, 就不須要結束執行,只須要執行完 處理代碼後, 進行原來正常的執行流程。

在這裏,就是繼續 while True 循環。



若是咱們開發程序的時候,估計某個代碼段中可能出現好幾種類型的異常,能夠使用多個except 代碼段,分別捕獲多種類型的異常,以下

try:
    choice = input('輸入你的選擇:')
    if choice == '1':
        100/0
    elif choice == '2':
        [][2]
except ZeroDivisionError:
    print ('出現 ZeroDivisionError')
except IndexError  :
    print ('出現 IndexError')

  

若是 輸入’1’, 則會產生 ZeroDivisionError 異常, 就會被 except ZeroDivisionError 捕獲,執行對應的代碼

print ('出現 ZeroDivisionError')

  

若是 輸入’2’, 則會產生 IndexError 異常, 就會被 except IndexError 捕獲,執行對應的代碼

print ('出現 IndexError')

 

獲取異常對象

咱們使用except 語句匹配異常類型的時候, 能夠使用as關鍵字,後面加一個變量名,以下所示:

try:
    100/0
except ZeroDivisionError as e:
    print (f'異常對象信息:{e}')

  

這樣,運行代碼的時候,當try中的語句產生異常對象時,就會 把產生的異常對象賦值給as後的變量。

上面的代碼,運行輸出

異常對象信息:division by zero

產生的異常對象賦值給了變量 e。

這樣咱們就能夠在後續的代碼中獲得產生的異常對象的信息。

匹配全部異常

若是咱們在寫一段代碼的時候,不知道這段代碼會拋出什麼樣的異常,而且咱們不但願程序由於異常而停止。

這時咱們能夠匹配全部類型的異常,這樣任何類型的異常發生都不會終止程序了。 以下:

try:
    100/0
except Exception as e:
    print('未知異常:', e)

  

由於全部的異常都是 Exception 的子類。 因此 Exception能匹配全部類型的異常。

except 爲空,也能夠匹配全部類型的異常,並且能夠經過traceback庫,顯示異常的信息和異常產生處的函數調用棧的信息,以下

import traceback

try:
    100/0
except :
    print(traceback.format_exc())

  

上面的代碼會打印出致使異常的詳細的函數調用棧的信息,以下

Traceback (most recent call last):
  File "xxxx/xxx.py", line 4, in <module>
    100/0
ZeroDivisionError: division by zero

  

 

自定義異常

異常類型都是 繼承自Exception的類,表示各類類型的錯誤。

咱們也能夠本身定義異常,好比咱們寫一個用戶註冊的函數, 要求用戶輸入的電話號碼只能是中國的電話號碼,而且電話號碼中不能有非數字字符。

能夠定義下面這兩種異常類型:

# 異常對象,表明電話號碼有錯誤的字符
class InvalidCharError(Exception):
    pass

# 異常對象,表明電話號碼非中國號碼
class NotChinaTelError(Exception):
    pass

  

定義了上面的異常,當用戶輸入電話號碼時,出現相應錯誤的時候,咱們就能夠使用raise 關鍵字來拋出對應的自定義異常

def  register():
    tel = input('請註冊您的電話號碼:')

    # 若是有非數字字符
    if not tel.isdigit(): 
        raise InvalidCharError

    # 若是不是以86開頭,則不是中國號碼
    if not tel.startswith('86'): 
        raise NotChinaTelError
    
    return tel

try:
    ret = register()
except InvalidCharError:
    print('電話號碼中有錯誤的字符')
except NotChinaTelError:
    print('非中國手機號碼')
相關文章
相關標籤/搜索