在Python2.6和3.0之前,可以使用類實例和字符串對象來定義異常,但是在字符串對象來定義異常的功能在2.6和3.0的版本中被刪除了。
#基於字符串對象來定義異常:
mystring="myerror"
try:
raise mystring
except mystring:
print("exception happened")
Python現已刪除字符串對象的異常,更推薦使用基於類的異常。
基於類的異常
基於類的異常與基於字符串的異常不同,
- 基於字符串的異常是通過對象識別來匹配的,也就是說except子句是通過Python的is測試來捕捉異常的
- 類異常則是由超類關係進行匹配,只要except子句列舉了該類或者該類的任意超類名,都會被捕捉到。這種基於繼承樹的類異常捕捉擁有更好的可維護性。讓異常可以有清晰的分類,捕捉時會更加靈活。
也就是說類異常可以捕捉列出在except子句後的類,以及該類樹中所有較低位置的子類。
- 在Python3.0中,類異常都是繼承自Exception類。
- 異常的處理中,總是會用引發和捕捉一個類實例對象。
內置Exception類
在Python3.0中的所有熟悉的異常,都是預定義的類,可以作爲內置變量名。此外,Python把內置異常組織成層次,來支持各種捕捉模式:
- BaseException
異常的頂級根類。這個類不能由用戶自定義的類直接繼承(使用Exception類繼承),它提供了子類的默認打印狀態和打印行爲。如果在這個類的實例上調用內置函數str,則會返回創建該實例時候所傳遞的構造函數參數的顯示字符串,這個字符串會在出錯時打印出來,自定義的異常類,也可以重新編寫str函數來顯示自己需要打印的異常信息。
>>> raise IndexError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError
>>> raise IndexError("Hello!")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: Hello! #打印出構造實例時所傳遞的字符串
>>>
- Exception
這個類直接繼承自BaseException類,並且是其它內置異常類的超類,幾乎所有用戶定義的類都應該繼承自這個類,事實上,Exception用於except分句時,可以用作try語句的全捕獲,並且比一條空的except語句更精確。 - ArithmeticError
所有數值錯誤的超類(也是Exception的一個子類) - OverflowError
識別特定的數值錯誤的子類
定製打印內容
由上面的內容我們可以知道,默認情況下,由創建實例時傳遞進入的字符串,可以被異常類記錄下來顯示,這是因爲BaseException中str函數可以記錄下傳遞進入的字符串。在定製自己的str內置函數(由print調用)時,可以用來定製打印內容:
>>> class myerror(Exception):
... def __str__(self):
... return "my error exception"
...
>>> lxm=myerror()
>>> raise lxm
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.myerror: my error exception #打印出自定義的內容
>>>
通過異常類的構造函數,還能提供Python代碼異常的細節。
>>> class myerror(Exception):
... def __init__(self,line,filename):
... self.line=line
... self.filename=filename
... def __str__(self):
... return "my error exception at %d of %s" % (self.line,self.filename)
...
>>> raise myerror(42,"text") #調用構造函數,傳遞相關信息。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.myerror: my error exception at 42 of text
>>>
異常類中還可以寫特定的函數和方法(比如將錯誤信息寫入log文件等等),這樣的類方法使得異常處理更簡單,就只是調用相關類中的方法就能達到效果。
小結
異常在Python中是以類的形式存在,用戶可以繼承Exception類來自定義自己的異常類。在異常類對象中,可以繼承一些內置函數,讓異常類繼承超類的一些行爲。異常類的繼承機制,還能在捕捉異常時,讓我們捕捉異常更加方便和針對性,超類會變成異常分類的名稱,而超類下的子類可以讓該異常分類更加細化。