Python異常處理入門
作者:黎智煊,叩丁狼高階講師。本文為原創文章,轉載請註明出處。
什麼是異常?
異常即是一個事件,該事件會在程式執行過程中發生,影響了程式的正常執行。
-
一般情況下,在Python無法正常處理程式時就會發生一個異常。
-
異常是Python物件,表示一個錯誤。
-
當Python指令碼發生異常時我們需要捕獲處理它,否則程式會終止執行。
-
捕捉異常可以使用
try/except
語句。 -
try/except
語句用來檢測try語句塊中的錯誤,從而讓except
如果你不想在異常發生時結束你的程式,只需在try裡捕獲它。
語法:
以下為簡單的try….except…else的語法:
try:
<語句> #執行別的程式碼
except <名字>:
<語句> #如果在try部份引發了'name'異常
except <名字>,<資料>:
<語句> #如果引發了'name'異常,獲得附加的資料
else:
<語句> #如果沒有異常發生
try的工作原理
-
try的工作原理是,當開始一個try語句後,python就在當前程式的上下文中作標記,這樣當異常出現時就可以回到這裡,try子句先執行,接下來會發生什麼依賴於執行時是否出現異常。
-
如果當try後的語句執行時發生異常,python就跳回到try並執行第一個匹配該異常的except子句,異常處理完畢,控制流就通過整個try語句(除非在處理異常時又引發新的異常)。
- 如果在try後的語句裡發生了異常,卻沒有匹配的except子句,異常將被遞交到上層的try,或者到程式的最上層(這樣將結束程式,並列印預設的出錯資訊)。
- 如果在try子句執行時沒有發生異常,python將執行else語句後的語句(如果有else的話),然後控制流通過整個try語句。
下面先簡單瞭解看一下關於python異常的型別,然後下一節再詳細
舉例說明如何使用python的異常處理.
python標準異常
異常名稱 | 描述 |
---|---|
BaseException | 所有異常的基類 |
SystemExit | 直譯器請求退出 |
KeyboardInterrupt | 使用者中斷執行(通常是輸入^C) |
Exception | 常規錯誤的基類 |
StopIteration | 迭代器沒有更多的值 |
GeneratorExit | 生成器(generator)發生異常來通知退出 |
StandardError | 所有的內建標準異常的基類 |
ArithmeticError | 所有數值計算錯誤的基類 |
FloatingPointError | 浮點計算錯誤 |
OverflowError | 數值運算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有資料型別) |
AssertionError | 斷言語句失敗 |
AttributeError | 物件沒有這個屬性 |
EOFError | 沒有內建輸入,到達EOF 標記 |
EnvironmentError | 作業系統錯誤的基類 |
IOError | 輸入/輸出操作失敗 |
OSError | 作業系統錯誤 |
WindowsError | 系統呼叫失敗 |
ImportError | 匯入模組/物件失敗 |
LookupError | 無效資料查詢的基類 |
IndexError | 序列中沒有此索引(index) |
KeyError | 對映中沒有這個鍵 |
MemoryError | 記憶體溢位錯誤(對於Python 直譯器不是致命的) |
NameError | 未宣告/初始化物件 (沒有屬性) |
UnboundLocalError | 訪問未初始化的本地變數 |
ReferenceError | 弱引用(Weak reference)試圖訪問已經垃圾回收了的物件 |
RuntimeError | 一般的執行時錯誤 |
NotImplementedError | 尚未實現的方法 |
SyntaxError | Python 語法錯誤 |
IndentationError | 縮排錯誤 |
TabError | Tab 和空格混用 |
SystemError | 一般的直譯器系統錯誤 |
TypeError | 對型別無效的操作 |
ValueError | 傳入無效的引數 |
UnicodeError | Unicode 相關的錯誤 |
UnicodeDecodeError | Unicode 解碼時的錯誤 |
UnicodeEncodeError | Unicode 編碼時錯誤 |
UnicodeTranslateError | Unicode 轉換時錯誤 |
Warning | 警告的基類 |
DeprecationWarning | 關於被棄用的特徵的警告 |
FutureWarning | 關於構造將來語義會有改變的警告 |
OverflowWarning | 舊的關於自動提升為長整型(long)的警告 |
PendingDeprecationWarning | 關於特性將會被廢棄的警告 |
RuntimeWarning | 可疑的執行時行為(runtime behavior)的警告 |
SyntaxWarning | 可疑的語法的警告 |
UserWarning | 使用者程式碼生成的警告 |
try的工作原理
當開始一個try語句後,python就在當前程式的上下文中作標記,這樣當異常出現時就可以回到這裡,try子句先執行,接下來會發生什麼依賴於執行時是否出現異常。
- 如果當try後的語句執行時發生異常,
python就跳回到try並執行第一個匹配該異常的except子句
,異常處理完畢,控制流就通過整個try語句(除非在處理異常時又引發新的異常)。 - 如果在try後的語句裡發生了異常,
卻沒有匹配的except子句,異常將被遞交到上層的try
,或者到程式的最上層(這樣將結束程式,並列印預設的出錯資訊)。 - 如果在try子句執行時沒有發生異常,python將執行else語句後的語句(如果有else的話),然後控制流通過整個try語句。
-
在程式執行的過程中,如果發生了錯誤,可以事先約定返回一個錯誤程式碼,這樣,就可以知道是否有錯,以及出錯的原因。在作業系統提供的呼叫中,返回錯誤碼非常常見。比如開啟檔案的函式
open()
,成功時返回檔案描述符(就是一個整數),出錯時返回-1
。
- 用錯誤碼來表示是否出錯十分不便,因為函式本身應該返回的正常結果和錯誤碼混在一起,造成呼叫者必須用大量的程式碼來判斷是否出錯:
def foo():
r = some_function()
if r==(-1):
return (-1)
# do something
return r
def bar():
r = foo()
if r==(-1):
print('Error')
else:
pass
- 一旦出錯,還要一級一級上報,直到某個函式可以處理該錯誤(比如,給使用者輸出一個錯誤資訊)。
所以高階語言通常都內建了一套try...except...finally...
的錯誤處理機制,Python也不例外。
try
讓我們用一個例子來看看try
的機制:
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
當我們認為某些程式碼可能會出錯時,就可以用try
來執行這段程式碼,如果執行出錯,則後續程式碼不會繼續執行,而是直接跳轉至錯誤處理程式碼,即except
語句塊,執行完except
後,如果有finally
語句塊,則執行finally
語句塊,至此,執行完畢。
上面的程式碼在計算10 / 0
時會產生一個除法運算錯誤:
try...
except: division by zero
finally...
END
從輸出可以看到,當錯誤發生時,後續語句print('result:', r)
不會被執行,except
由於捕獲到ZeroDivisionError
,因此被執行。最後,finally
語句被執行。然後,程式繼續按照流程往下走。
下面舉個簡單的例子,在test.py裡面寫入以下程式碼
- 下面是簡單的例子,它開啟一個檔案,
在該檔案中的內容寫入內容,且並未發生異常:
try:
fh = open("testfile", "w")
fh.write("這是一個測試檔案,用於測試異常!!")
except IOError:
print "Error: 沒有找到檔案或讀取檔案失敗"
else:
print("內容寫入檔案成功")
fh.close()
執行程式
python test.py
內容寫入檔案成功
cat testfile # 檢視寫入的內容
這是一個測試檔案,用於測試異常!!
下面舉一個故意引發異常的例子
- 下面是簡單的例子,
它開啟一個檔案,在該檔案中的內容寫入內容,但檔案沒有寫入許可權,發生了異常:
try:
fh = open("testfile", "w")
fh.write("這是一個測試檔案,用於測試異常!!")
except IOError:
print("Error: 沒有找到檔案或讀取檔案失敗")
else:
print("內容寫入檔案成功")
fh.close()
在執行程式碼前為了測試方便,我們可以先去掉 testfile 檔案的寫許可權,命令如下:chmod -w testfile
再執行以上程式碼:python test.py
Error: 沒有找到檔案或讀取檔案失敗