轉自:白月黑羽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('非中國手機號碼')