1. 程式人生 > 實用技巧 >Python基礎-異常

Python基礎-異常

異常捕獲

常見異常型別

Exception:頂級異常類,大部分異常類都是它的子類。
SyntaxError:語法錯誤
TypeError:型別錯誤
ValueError:值錯誤
NameError:找不到名稱,比如變數名
IndexError:找不到索引,在序列中取值時出現
KeyError:對映中不存在鍵名,在字典中取一個不存在的key時出現
ZeroDivisionError:除法中除數為0時出現
FileNotFoundError:找不到檔案錯誤

捕獲指定異常

異常捕獲的寫法結構是try-except,下面模擬一個除數為0的異常。

a = 10
b = 0
try:
result = a / b
print(f"結果是:{result}")
except ZeroDivisionError:
print('除數不能為0')

列印結果:

除數不能為0

我們雖然捕獲了ZeroDivisionError,但是也可能出現其他異常,比如a和b不是數字呢?那麼我們如果想單獨對每一種異常都進行精確捕獲與提示的話,可以多寫幾個except,針對性處理。

a = 10
b = 'abc'
try:
result = a / b
print(f"結果是:{result}")
except ZeroDivisionError:
print('除數不能為0')
except TypeError:
print('型別錯誤')

列印結果:

型別錯誤

如果想多個異常統一處理,也可以同時捕獲多個異常。

a = 10
b = 'abc'
try:
result = a / b
print(f"結果是:{result}")
except (ZeroDivisionError,TypeError) as e:
print(e)

列印結果:

unsupported operand type(s) for /: 'int' and 'str'

捕獲所有異常

捕獲所有異常是最省心的做法,你不用去糾結到底這段程式碼可能會出現哪些異常。

a = 10
b = 'abc'
try:
result = a / b
print(f"結果是:{result}")
except:
print('出現異常了') 列印結果:
出現異常了

主動丟擲異常

raise語句對標java和PHP中的throw,作用是丟擲異常。

a = 10
b = 0
try:
if b == 0 : raise Exception('竟然是0!')
result = a / b
print(f"結果是:{result}")
except Exception as e:
print(f'出現異常了:{e}')

列印結果:

出現異常了:竟然是0!

raise不僅可以在try-except語句塊裡面用,也可以在全域性使用,在try-except裡面丟擲異常,會被except捕獲,如果在沒有try-except程式碼中使用的話,異常就會向上傳遞,傳給呼叫方,直到傳到主程式全域性空間,然後停止程式執行,打印出棧跟蹤資訊。

未發生異常時

try-except語句還可以包含else程式碼塊,讓我們可以像條件判斷一樣進行異常處理,如果出現異常怎麼辦,如果沒有異常又怎麼辦。

a = 10
b = 2
try:
if b == 0 : raise Exception('竟然是0!')
result = a / b
print(f"結果是:{result}")
except Exception as e:
print(f'出現異常了:{e}')
else:
print('程式一切正常')

列印結果:

結果是:5.0
程式一切正常

掃尾工作

try-except還有一個finally程式碼塊,無論是否異常都一定會執行finally程式碼塊中的程式碼,比如開啟檔案之後做一些業務處理,無論過程是否出現異常,都必須要關閉檔案,那麼關閉檔案的操作就應該放在finally程式碼塊中。

a = 10
b = 0
try:
if b == 0 : raise Exception('竟然是0!')
result = a / b
print(f"結果是:{result}")
except Exception as e:
print(f'出現異常了:{e}')
else:
print('程式一切正常')
finally:
print('掃尾工作清理')

列印結果:

出現異常了:竟然是0!
掃尾工作清理

自定義異常

自定義異常類需要繼承Exception類,直接繼承或間接繼承都可以。

class MyError(Exception):
pass try:
raise MyError('隨便拋')
except MyError as e:
print(f'捕獲到了自定義異常:{e}')

列印結果:

捕獲到了自定義異常:隨便拋

如果你願意,也可以在自定義異常類中覆蓋父類的建構函式,或者新增方法都可以。