一個程序即使語法正確,也可能在執行過程中會產生錯誤,這些錯誤往往會導致程序非預期提前終止。
在程序執行中遇到的錯誤,我們稱之為異常(Exception)。
在程序中對異常進行處理可以提高用戶的體驗。
在Python中也提供了類似Java、C#等異常處理方法。
Python使用try, except 和 finally三個關鍵字來處理異常,在異常處理形式上與其它語言相同,但語法使用的關鍵字稍有不同。
把可能出現異常的語句放在try語句塊中,而異常的捕獲與處理過程放在 except 語句塊中。
在一次異常處理中可以包含多個except語句塊,以便用于捕獲和處理不同的異常。
不管異常是否發生,放在finally語句塊中的語句總會被執行到。利用這個機制可以在程序中用于釋放資源或在程序中出現異常時進行其他的處理操作,如保存游戲進度等。
在Python中也可以使用else語句塊配合異常處理。即沒有異常發生時執行else語句塊中的語句。
其語法格式如下:
try:
#可能出現異常的語句
except 異常類1 as 變量1:
#異常處理語句
except 異常類2 as 變量2:
#異常處理語句
...
finally:
#finally語句塊
上面語法格式中,except可以出現多次,finally語句塊是可選的語句塊。
下面舉例子來說明:
def divide(x, y):
try:
print(f"{x} / {y} = {x / y}")
except ZeroDivisionError as e:
print("發生錯誤:除數為0。")
divide(2008, 4)
divide(2008, 0)
divide(2008, 100)
輸出情況如下:
2008 / 4 = 502.0
發生錯誤:除數為0。
2008 / 100 = 20.08
下面是沒有異常處理的情況:
def divide(x, y):
print(f"{x} / {y} = {x / y}")
divide(2008, 4)
divide(2008, 0)
divide(2008,100)
輸出情況如下:
2008 / 4 = 502.0
從上面兩個例子可以看出,在可能出現異常的地方若不對異常進行處理,將導致程序非預期終止(第3個函數調用并沒有被執行),而使用異常處理后,在給出友好提示的同時,還能使程序繼續執行下去。
Traceback (most recent call last):
File "D:/01Lesson/PY/exceptionhandle02.py", line 5, in <module>
divide(2008, 0)
File "D:/01Lesson/PY/exceptionhandle02.py", line 2, in divide
print(f"{x} / {y} = {x / y}")
ZeroDivisionError: division by zero
在第1個例子中,我們使用了除數為0的異常類,并聲明了變量e。但在程序中并沒有使用它,實際上也可以省略它,省略時的樣子如下:
def divide(x, y):
try:
print(f"{x} / {y} = {x / y}")
except ZeroDivisionError:
print("發生錯誤:除數為0。")
divide(2008, 4)
divide(2008, 0)
divide(2008, 100)
輸出情況如下:
2008 / 4 = 502.0
發生錯誤:除數為0。
2008 / 100 = 20.08
也可以在輸出時直接輸出變量e。例子如下:
def divide(x, y):
try:
print(f"{x} / {y} = {x / y}")
except ZeroDivisionError as e:
print(e)
divide(2008, 4)
divide(2008, 0)
divide(2008, 100)
輸出情況如下:
2008 / 4 = 502.0
division by zero
2008 / 100 = 20.08
(1)BaseException 是所有內建異常的基類,不能被用戶由用戶定義的異常所繼承;由該基類直接派生的子類有:
①Exception 見(2)中的描述;
②GeneratorExit 當生成器或協同進程被關閉時引發的異常;
③KeyboardInterrupt 當用戶按下中斷鍵(通常是control-c 或delete)時引發的異常;
④SystemExit 由sys.exit()函數引發的異常。
(2)Exception 所有內建,非系統退出性異常都派生于此類,用戶定義的異常也由此類所派生;
(3)ArithmeticError 由算術錯誤導致的內建異常的基類: OverflowError, ZeroDivisionError, FloatingPointError.;
(4)BufferError 與緩沖區相關的操作無法執行時引發的異常;
(5)LookupError 當匹配或序列索引操作所提供的索引或鍵無效時引發的異常基類:IndexError, KeyError。
(1)AssertionError 當assert語句無效時引發的異常;
(2)AttributeError 當引用屬性或為其負值失敗時引發的異常;
(3)EOFError 當調用input()函數沒有讀取到數據而到達文件末尾(EOF)時而引發的異常;
(4)ImportError 當import語句加載模塊遇到問題時引發的異常;
(5)IndexError 序列操作下標超出范圍時引發的異常;
(6)KeyError 在匹配的鍵在鍵集中未找到時引發的異常;
(7)MemoryError 當操作耗盡內存時引發的異常;
(8)NameError 在局部或全局中未找到相關命名時引發的異常;
(9)TypeError 當運算或函數調用使用的對象不匹配時引發的異常;
(10)ZeroDivisionError 在除法或取模運算中,第二個參數為0時引發的異常。
在實際中,一段代碼可能會產生多種異常,我們可以使用多個except語句塊來捕捉相應的異常進行處理。下面這個例子說明具有多個except語句塊時的使用方法。
v1 = input("請輸入被除數:")
v2 = input("請輸入除數:")
try:
x = float(v1)
y = float(v2)
q = x / y
print(f"{x}÷{y} = {q}")
except TypeError as te:
print(te)
except ZeroDivisionError as zde:
print(zde)
except ValueError as ve:
print(ve)
執行輸入與輸出情況:
請輸入被除數:100
請輸入除數:e
could not convert string to float: 'e'
請輸入被除數:100
請輸入除數:0
float division by zero
請輸入被除數:100
請輸入除數:5
100.0÷5.0 = 20.0
在Python 3.8.2 IDLE的執行情況如下圖所示:
在我們無法知道所有的異常類的情況下,我們可以使用except捕獲所有可能的異常。即在except塊中不必給出具體的異常類。下面一段程序演示了該種情況下的使用方法:
def divide(x, y):
try:
print(f"{x} / {y} = {x / y}")
except ZeroDivisionError as e:
print("發生錯誤:除數為0。")
except:
print("發生未知錯誤。")
divide(2008, 4)
divide(2008, 'a')
divide(2008, 0)
divide(2008, 100)
執行輸出結果如下:
2008 / 4 = 502.0
在我們無法知道程序具體發生哪些異常時,使用except捕獲未知異常是一件非常有益的事情。
發生未知錯誤。
division by zero
2008 / 100 = 20.08
else語句塊是可選部分。當try語句塊沒有捕獲到異常時,就會執行else語句塊中的內容。
下面程序中使用了else語句塊:
def divide(x, y):
try:
print(f"{x}/{y}={x/y}")
except ZeroDivisionError as e:
print(e)
else:
print("函數一切正常。")
divide(2021, 3)
divide(2021, 0)
divide(2021, 10)
在Python 3.8.2 IDLE運行情況如下圖所示:
從上面的例子中可以看出,當程序執行過程中沒有遇到異常時就會輸出else語句塊中的內容:函數一切正常。
不管程序是否遇到了異常,finally語句塊都會被執行。這常常用于程序釋放資源,執行一些清理性工作。下面的例子演示了finally語句塊的使用。
def divide(x, y):
try:
print(f"{x}/{y}={x/y}")
except ZeroDivisionError as e:
print(e)
finally:
print("finally:清理活動。")
divide(2021, 3)
divide(2021, 0)
divide(2021, 10)
運行結果如下:
2021/3=673.6666666666666
finally:清理活動。
division by zero
finally:清理活動。
2021/10=202.1
finally:清理活動。
在Python 3.8.2 IDLE的運行情況如下圖所示:
以上是關于Python中異常處理的基本情況,在今后的文章中將進一步講解用戶自定義異常的方法。
本文(完)
新聞熱點
疑難解答