內建的例外¶
在 Python 中,所有例外必須是從 BaseException
衍生的類別的實例。在陳述式 try
搭配 except
子句裡提到一個特定的類別時,那個子句也會處理任何從該類別衍生的例外類別(但不會處理該類別衍生自的例外類別)。兩個不是由子類別關係關聯起來的例外類別永遠不相等,就算它們有相同的名稱也是如此。
此章節裡列出的內建例外可以從直譯器或內建函式產生。除了特別提到的地方之外,它們會有一個關聯值表示錯誤發生的詳細原因。這可能是一個字串,或者是一些資訊項目組成的元組(例如一個錯誤代碼及一個解釋該代碼的字串)。這個關聯值通常當作引數傳遞給例外類別的建構函式。
使用者的程式碼可以引發內建例外。這可以用來測試例外處理器或者用來回報一個錯誤條件,就像直譯器會引發相同例外的情況;但需要注意的是沒有任何方式可以避免使用者的程式碼引發不適當的錯誤。
可以從內建的例外類別定義新的例外子類別;程式設計師被鼓勵從 Exception
類別或其子類別衍生新的例外,而不是從 BaseException
來衍生。更多關於定義例外的資訊可以在 Python 教學中的使用者自定的例外裡取得。
例外的情境¶
三個例外物件上的屬性提供關於引發此例外的情境的資訊:
- BaseException.__context__¶
- BaseException.__cause__¶
- BaseException.__suppress_context__¶
當引發一個新的例外而同時有另一個例外已經正在被處理時,這個新例外的
__context__
屬性會自動被設成那個已處理的例外。當使用except
或finally
子句或with
陳述式的時候例外會被處理。這個隱含的例外情境可以透過使用
from
搭配raise
來補充明確的原因:raise new_exc from original_exc
在
from
後面的運算式必須是一個例外或None
。它將會被設定成所引發例外的__cause__
。設定__cause__
也隱含地設定__suppress_context__
屬性為True
,因此使用raise new_exc from None
實際上會以新的例外取代舊的例外以利於顯示(例如轉換KeyError
為AttributeError
),同時保持舊的例外可以透過__context__
取得以方便 debug 的時候檢查。預設的回溯 (traceback) 顯示程式碼會顯示這些連鎖的例外 (chained exception) 加上例外本身的回溯。當存在的時候,在
__cause__
中明確地連鎖的例外總是會被顯示。而在__context__
中隱含地連鎖的例外只有當__cause__
是None
且__suppress_context__
是 false 時才會顯示。在任一種情況下,例外本身總是會顯示在任何連鎖例外的後面,因此回溯的最後一列總是顯示最後一個被引發的例外。
繼承自內建的例外¶
使用者的程式碼可以建立繼承自例外類型的子類別。建議一次只繼承一種例外類型以避免在基底類別之間如何處理 args
屬性的任何可能衝突,以及可能的記憶體佈局 (memory layout) 不相容。
CPython 實作細節: 為了效率,大部分的內建例外使用 C 來實作,參考 Objects/exceptions.c。一些例外有客製化的記憶體佈局,使其不可能建立一個繼承多種例外類型的子類別。類型的記憶體佈局是實作細節且可能會在不同 Python 版本間改變,造成未來新的衝突。因此,總之建議避免繼承多種例外類型。
基底類別 (base classes)¶
以下的例外大部分被用在當作其他例外的基底類別。
- exception BaseException¶
所有內建例外的基底類別。這不是為了讓使用者定義的類別直接繼承(可以使用
Exception
)。如果在這個類別的實例上呼叫str()
,會回傳實例的引數的表示,或者沒有引數的時候會回傳空字串。- with_traceback(tb)¶
此方法設定 tb 為該例外的新的回溯並回傳該例外物件。在 PEP 3134 的例外連鎖功能變得可用之前,此方法曾被更普遍使用。下面的範例顯示我們如何將
SomeException
的實例轉換為OtherException
的實例同時保留回溯。一旦被引發,目前的 frame 會被加進OtherException
的回溯,就像原來SomeException
的回溯會發生的一樣,我們允許它被傳遞給呼叫者:try: ... except SomeException: tb = sys.exception().__traceback__ raise OtherException(...).with_traceback(tb)
- __notes__¶
該例外的備註串列,使用
add_note()
來新增。此屬性在add_note()
被呼叫的時候建立。在 3.11 版被加入.
- exception Exception¶
所有內建、非系統退出 (non-system-exiting) 的例外都衍生自此類別。所有使用者定義的例外應該也要衍生自此類別。
- exception ArithmeticError¶
各種運算錯誤所引發的那些內建例外:
OverflowError
、ZeroDivisionError
、FloatingPointError
的基底類別。
- exception BufferError¶
當緩衝 (buffer) 相關的操作無法被執行時會引發此例外。
- exception LookupError¶
當使用在對映或序列上的鍵或索引是無效的時候所引發的例外:
IndexError
、KeyError
的基底類別。這可以被codecs.lookup()
直接引發。
實體例外¶
以下的例外是通常會被引發的例外。
- exception AttributeError¶
當屬性參照(參考 Attribute references)或賦值失敗的時候被引發。(當物件根本不支援屬性參照或屬性賦值的時候,
TypeError
會被引發。)name
和obj
屬性可以使用建構函式的僅限關鍵字 (keyword-only) 引數來設定。當被設定的時候,它們分別代表被嘗試存取的屬性名稱以及被以該屬性存取的物件。在 3.10 版的變更: 新增
name
與obj
屬性。
- exception EOFError¶
當
input()
函式在沒有讀到任何資料而到達檔案結尾 (end-of-file, EOF) 條件的時候被引發。(注意:io.IOBase.read()
和io.IOBase.readline()
方法當達到 EOF 時會回傳空字串。)
- exception FloatingPointError¶
目前沒有被使用。
- exception GeneratorExit¶
當 generator 或 coroutine 被關閉的時候被引發;參考
generator.close()
和coroutine.close()
。此例外直接繼承自BaseException
而不是Exception
,因為技術上來說這不是一個錯誤。
- exception ImportError¶
當
import
陳述式嘗試載入模組遇到問題的時候會被引發。當from ... import
裡的 "from list" 包含找不到的名稱時也會被引發。可選的僅限關鍵字引數 name 和 path 設定對應的屬性:
- name¶
嘗試引入 (import) 的模組名稱。
- path¶
觸發此例外的任何檔案的路徑。
- exception ModuleNotFoundError¶
ImportError
的子類別,當模組不能被定位的時候會被import
所引發。當在sys.modules
裡找到None
時也會被引發。在 3.6 版被加入.
- exception IndexError¶
當序列的索引超出範圍的時候會被引發。(切片索引 (slice indices) 會默默地被截短使其能落在允許的範圍內;如果索引不是整數,
TypeError
會被引發。)
- exception KeyError¶
當對映(字典)的鍵無法在已存在的鍵的集合中被找到時會被引發。
- exception KeyboardInterrupt¶
當使用者輸入中斷鍵 (interrupt key)(一般來說是 Control-C 或 Delete)時會被引發。在執行過程中,會定期檢查是否產生中斷。此例外繼承自
BaseException
以防止意外地被捕捉Exception
的程式碼所捕捉,而因此讓直譯器無法結束。備註
捕捉
KeyboardInterrupt
需要特殊的考量。因為它可以在無法預期的時間點被引發,可能在某些情況下讓正在跑的程式處在一個不一致的狀態。一般來說最好讓KeyboardInterrupt
越快結束程式越好,或者完全避免引發它。(參考 Note on Signal Handlers and Exceptions。)
- exception MemoryError¶
當一個操作用光了記憶體但情況還可能被修復 (rescued)(透過刪除一些物件)的時候被引發。關聯值是一個字串,表示什麼類型的(內部)操作用光了記憶體。需注意的是因為底層的記憶體管理架構(C 的
malloc()
函式),直譯器可能無法總是完整地從該情況中修復;僅管如此,它還是引發例外以讓堆疊回溯可以被印出,以防原因出在失控的程式。
- exception NameError¶
當找不到本地或全域的名稱時會被引發。這只應用在不合格的名稱 (unqualified name) 上。關聯值是一個錯誤訊息,包含那個無法被找到的名稱。
name
屬性可以使用僅限關鍵字引數來設定到建構函式。當被設定的時候它代表被嘗試存取的變數名稱。在 3.10 版的變更: 新增
name
屬性。
- exception NotImplementedError¶
此例外衍生自
RuntimeError
。在使用者定義的基礎類別裡,當抽象方法要求衍生類別覆寫該方法時應該要引發此例外,或者當類別正在開發中,可用此例外表示還需要加入真正的實作。備註
此例外不應該用來表示根本沒有要支援的運算子或方法 ── 在這個情況下可以讓該運算子或方法保持未定義,或者如果是子類別的話將其設成
None
。備註
NotImplementedError
和NotImplemented
雖然有相似的名稱和目的但並不是可互換的。參考NotImplemented
裡關於何時使用的細節。
- exception OSError([arg])¶
- exception OSError(errno, strerror[, filename[, winerror[, filename2]]])
當系統函式回傳系統相關錯誤,包含像"找不到檔案"或"硬碟已滿"的 I/O 失敗會引發此例外(而非不合法的引數或其他次要的錯誤)。
建構函式的第二種形式會設定以下描述的相對應屬性。如果沒有給定則屬性預設為
None
。為了向後相容,如果傳入三個引數,args
屬性只會是包含建構函式前兩個引數的雙元素元組。如同下面的作業系統例外所描述,實際上建構函式通常回傳
OSError
的子類別。會依據最後errno
的值決定特定子類別。這個行為只發生在直接建構OSError
或透過別名,且產生子類別的時候不會被繼承。- errno¶
從 C 變數
errno
而來的數值錯誤代碼。
- winerror¶
在 Windows 下,這會提供你原生的 Windows 錯誤代碼。而
errno
屬性是一個該原生錯誤代碼對於 POSIX 來說的近似翻譯。在 Windows 下,如果建構函式引數 winerror 是整數,則
errno
屬性會根據該 Windows 錯誤代碼來決定,且 errno 引數會被忽略。在其他平台上,winerror 引數會被忽略,而winerror
屬性會不存在。
- strerror¶
作業系統提供的對應錯誤訊息。在 POSIX 下會使用 C 函式
perror()
做格式化,而在 Windows 下會使用FormatMessage()
。
- filename¶
- filename2¶
對於包含檔案系統路徑的例外(像是
open()
或os.unlink()
),filename
是傳入函式的檔案名稱。對於包含兩個檔案系統路徑的函式(像是os.rename()
),filename2
對應到傳入函式的第二個檔案名稱。
在 3.3 版的變更:
EnvironmentError
、IOError
、WindowsError
、socket.error
、select.error
及mmap.error
已合併進OSError
,而建構函式可能會回傳子類別。在 3.4 版的變更:
filename
屬性現在是傳入函式的原始檔名,而不是從檔案系統編碼和錯誤處理函式編碼或解碼過的名稱。並且新增 filename2 建構函式引數與屬性。
- exception OverflowError¶
當運算操作的結果太大而無法表示的時候會引發此例外。這不會發生在整數上(會改成引發
MemoryError
而不是放棄)。然而,因為一些歷史因素,OverflowError 有時候會因為整數在要求範圍之外而引發。因為在 C 裡面缺乏浮點數例外處理的標準化,大部分的浮點數運算都沒有被檢查。
- exception RecursionError¶
此例外衍生自
RuntimeError
。當直譯器偵測到超過最大的遞迴深度(參考sys.getrecursionlimit()
)時會引發此例外。在 3.5 版被加入: 在之前,會引發一般的
RuntimeError
。
- exception ReferenceError¶
當一個被
weakref.proxy()
函式建立的弱參照代理 (weak reference proxy) 被用來存取已經被垃圾回收 (garbage collected) 的參照物屬性時會引發此例外。更多關於弱參照的資訊參考weakref
模組。
- exception RuntimeError¶
當偵測到一個不屬於任何其他種類的錯誤時會引發此例外。關聯值是一個表示確切什麼地方出錯的字串。
- exception StopIteration¶
會被內建函式
next()
及 iterator 的__next__()
方法引發,用來表示疊代器沒有更多項目可以產生。當 generator 或 coroutine 函式回傳時,新的
StopIteration
實例會被引發,而該函式的回傳值會被用來當作此例外建構函式的value
參數。如果產生器程式直接或間接引發
StopIteration
,則其會被轉換成RuntimeError
(保留StopIteration
作為新例外的成因)。在 3.3 版的變更: 新增
value
屬性且產生器函式可以用它來回傳值。在 3.5 版的變更: 透過
from __future__ import generator_stop
引入 RuntimeError 的轉換,參考 PEP 479。在 3.7 版的變更: 預設對所有程式啟用 PEP 479:在產生器引發的
StopIteration
錯誤會轉換成RuntimeError
。
- exception StopAsyncIteration¶
此例外必須被 asynchronous iterator 物件的
__anext__()
方法引發來停止疊代。在 3.5 版被加入.
- exception SyntaxError(message, details)¶
當剖析器遇到語法錯誤時會引發此例外。這可能發生在
import
陳述式、在呼叫內建函式compile()
、exec()
或eval()
的時候,或者在讀取初始腳本或標準輸入(也包含互動式)的時候。例外實例的
str()
只回傳錯誤訊息。Details 是個元組,其成員也能夠以分開的屬性取得。- filename¶
發生語法錯誤所在的檔案名稱。
- lineno¶
發生錯誤所在檔案的列號。這是以 1 開始的索引:檔案第一列的
lineno
是 1。
- offset¶
發生錯誤所在該列的欄號 (column)。這是以 1 開始的索引:該列第一個字元的
offset
是 1。
- text¶
涉及該錯誤的原始程式碼文字。
- end_lineno¶
發生錯誤所在檔案的結束列號。這是以 1 開始的索引:檔案第一列的
lineno
是 1。
- end_offset¶
發生錯誤所在該結束列的欄號。這是以 1 開始的索引:該列第一個字元的
offset
是 1。
對於發生在 f-string 欄位的錯誤,訊息會以 "f-string: " 為前綴,而偏移量 (offset) 是從替代表達式建構的文字的偏移量。例如編譯 f'Bad {a b} field' 會得到這個 args 屬性:('f-string: ...', ('', 1, 2, '(a b)n', 1, 5))。
在 3.10 版的變更: 新增
end_lineno
與end_offset
屬性。
- exception IndentationError¶
與不正確的縮排有關的語法錯誤的基礎類別。這是
SyntaxError
的子類別。
- exception TabError¶
當縮排包含製表符號 (tab) 和空白的不一致用法時會引發此例外。這是
IndentationError
的子類別。
- exception SystemError¶
當直譯器找到一個內部錯誤,但該情況看起來沒有嚴重到要讓它放棄所有的希望時會引發此例外。關聯值是一個表示什麼地方出錯的字串(以低階的方式表達)。
你應該向你的 Python 直譯器作者或維護者回報此錯誤。務必要回報該 Python 直譯器的版本(
sys.version
;這也會在互動式 Python 會話的開頭被印出)、確切的錯誤訊息(該例外的關聯值)及如果可能的話,觸發此錯誤的程式來源。
- exception SystemExit¶
此例外會被
sys.exit()
函式引發。它繼承自BaseException
而不是Exception
因此不會被捕捉Exception
的程式意外地捕捉。這允許例外可以正確地向上傳遞並導致直譯器結束。當它未被處理時,Python 直譯器會結束;不會印出堆疊回溯。建構函式接受跟傳入sys.exit()
一樣的可選引數。如果該值是整數,它會指定系統的結束狀態(傳入 C 的exit()
函式 );如果它是None
,結束狀態會是 0;如果它是其他類型(例如字串),則物件的值會被印出而結束狀態是 1。對
sys.exit()
的呼叫會轉譯成例外讓負責清理的處理函式(try
陳述式的finally
子句)可以被執行,且讓除錯器可以在不冒著失去控制的風險下執行腳本。如果在絕對有必要立即結束的情況(例如在子行程呼叫完os.fork()
之後 )可以使用os._exit()
函式。- code¶
傳入建構函式的結束狀態或錯誤訊息。(預設是
None
。 )
- exception TypeError¶
當一個操作或函式被用在不適合的類型的物件時會引發此例外。關聯值是一個字串,提供關於不相符類型的細節。
此例外可能被使用者程式碼引發,以表示並不支援物件上所嘗試的操作,且本來就無意這樣做。如果一個物件有意要支援某個給定的操作但尚未提供實作,該引發的正確例外是
NotImplementedError
。傳入錯誤類型的引數(例如當預期傳入
int
卻傳入list
)應該要導致TypeError
,但傳入帶有錯誤值的引數(例如超出預期範圍的數值)應該要導致ValueError
。
- exception UnicodeError¶
當 Unicode 相關的編碼或解碼錯誤發生時會引發此例外。這是
ValueError
的子類別。UnicodeError
有屬性描述編碼或解碼錯誤。例如err.object[err.start:err.end]
會提供讓編解碼器失敗的具體無效輸入。- encoding¶
引發錯誤的編碼名稱。
- reason¶
描述特定編解碼器錯誤的字串。
- object¶
編解碼器嘗試編碼或解碼的物件。
- exception UnicodeEncodeError¶
在編碼當中發生 Unicode 相關錯誤時會引發此例外。這是
UnicodeError
的子類別。
- exception UnicodeDecodeError¶
在解碼當中發生 Unicode 相關錯誤時會引發此例外。這是
UnicodeError
的子類別。
- exception UnicodeTranslateError¶
在轉譯當中發生 Unicode 相關錯誤時會引發此例外。這是
UnicodeError
的子類別。
- exception ValueError¶
當一個操作或函式收到引數是正確類型但是不適合的值,且該情況無法被更精確的例外例如
IndexError
所描述時會引發此例外。
- exception ZeroDivisionError¶
當除法或模數運算 (modulo operation) 的第二個引數是 0 的時候會引發此例外。關聯值是一個字串,表示運算元及運算的類型。
以下例外是為了相容於之前版本而保留;從 Python 3.3 開始,它們是 OSError
的別名。
- exception EnvironmentError¶
- exception IOError¶
- exception WindowsError¶
僅限於在 Windows 中使用。
作業系統例外¶
以下的例外是 OSError
的子類別,它們根據系統錯誤代碼來引發。
- exception BlockingIOError¶
當設置為非阻塞操作的物件(例如 socket)上的操作將要阻塞時會引發此例外。對應到
errno
EAGAIN
、EALREADY
、EWOULDBLOCK
及EINPROGRESS
。除了
OSError
的那些屬性之外,BlockingIOError
有多一個屬性:
- exception ConnectionError¶
連線相關問題的基礎類別。
子類別有
BrokenPipeError
、ConnectionAbortedError
、ConnectionRefusedError
及ConnectionResetError
。
- exception BrokenPipeError¶
ConnectionError
的子類別,當嘗試寫入管道 (pipe) 同時另一端已經被關閉時會引發此例外,或者當嘗試寫入已關閉寫入的 socket 時也會引發。對應到errno
EPIPE
及ESHUTDOWN
。
- exception ConnectionAbortedError¶
ConnectionError
的子類別。當一個連線的嘗試被對等端點 (peer) 中斷時會引發此例外。對應到errno
ECONNABORTED
。
- exception ConnectionRefusedError¶
ConnectionError
的子類別。當一個連線的嘗試被對等端點拒絕時會引發此例外。對應到errno
ECONNREFUSED
。
- exception ConnectionResetError¶
ConnectionError
的子類別。當一個連線被對等端點重置時會引發此例外。對應到errno
ECONNRESET
。
- exception InterruptedError¶
當系統呼叫被傳入的信號中斷時會引發此例外。對應到
errno
EINTR
。在 3.5 版的變更: 現在當 syscall 被信號中斷時 Python 會重試系統呼叫而不會引發
InterruptedError
,除非信號處理器引發例外(理由可參考 PEP 475)。
- exception IsADirectoryError¶
當在目錄上請求檔案操作(例如
os.remove()
)時會引發此例外。對應到errno
EISDIR
。
- exception NotADirectoryError¶
當在某個不是目錄的東西上請求目錄操作(例如
os.listdir()
)時會引發此例外。在大多數的 POSIX 平台上,如果嘗試操作開啟或遍歷一個當作目錄的非目錄檔案也會引發此例外。對應到errno
ENOTDIR
。
- exception PermissionError¶
當嘗試執行一個沒有合乎存取權限的操作時會引發此例外 — 例如檔案系統權限。對應到
errno
EACCES
、EPERM
及ENOTCAPABLE
。在 3.11.1 版的變更: WASI 的
ENOTCAPABLE
現在對應到PermissionError
。
在 3.3 版被加入: 加入以上所有的 OSError
子類別。
也參考
PEP 3151 — 改寫作業系統與 IO 例外階層
警告¶
以下的例外是當作警告的種類使用;更多細節參考 Warning Categories 文件。
- exception Warning¶
警告種類的基礎類別。
- exception UserWarning¶
使用者程式碼產生的警告的基礎類別。
- exception DeprecationWarning¶
關於已棄用功能的警告的基礎類別,且當那些警告是針對其他 Python 開發者。
會被預設的警告過濾器忽略,在
__main__
模組裡除外 (PEP 565)。啟用 Python 開發模式會顯示此警告。棄用原則描述在 PEP 387 裡。
- exception PendingDeprecationWarning¶
關於過時且預期未來要被棄用,但目前尚未被棄用的功能的警告的基礎類別。
因為發出關於可能即將被棄用的警告是不尋常的,此類別很少被使用,而對已經被棄用的情況會優先使用
DeprecationWarning
。會被預設的警告過濾器忽略。啟用 Python 開發模式會顯示此警告。
棄用原則描述在 PEP 387 裡。
- exception SyntaxWarning¶
關於可疑語法的警告的基礎類別。
- exception RuntimeWarning¶
關於可疑執行環境行為的警告的基礎類別。
- exception FutureWarning¶
關於已棄用功能的警告的基礎類別,且當那些警告是針對以 Python 寫的應用程式的終端使用者。
- exception ImportWarning¶
關於在模組引入的可能錯誤的警告的基礎類別。
會被預設的警告過濾器忽略。啟用 Python 開發模式會顯示此警告。
- exception UnicodeWarning¶
Unicode 相關警告的基礎類別。
- exception EncodingWarning¶
編碼相關警告的基礎類別。
細節參考選擇性加入的編碼警告。
在 3.10 版被加入.
- exception ResourceWarning¶
資源用法相關警告的基礎類別。
會被預設的警告過濾器忽略。啟用 Python 開發模式會顯示此警告。
在 3.2 版被加入.
例外群組¶
當需要引發多個不相關例外時會使用下列的類別。它們是例外階層的一部分所以可以像所有其他例外一樣使用 except
來處理。此外,它們會以包含的例外類型為基礎來比對其子群組而被 except*
辨認出來。
- exception ExceptionGroup(msg, excs)¶
- exception BaseExceptionGroup(msg, excs)¶
這兩個例外類型都將例外包裝在序列
excs
中。msg
參數必須是字串。這兩個類別的差異是BaseExceptionGroup
擴充了BaseException
且可以包裝任何例外,而ExceptionGroup
擴充了Exception
且只能包裝Exception
的子類別。這個設計使得except Exception
可以捕捉ExceptionGroup
但不能捕捉BaseExceptionGroup
。如果所有包含的例外都是
Exception
實例,BaseExceptionGroup
建構函式會回傳ExceptionGroup
而不是BaseExceptionGroup
,因此可以被使用來讓這樣的選擇自動化。另一方面來說,如果任何包含的例外不是Exception
的子類別,ExceptionGroup
建構函式會引發TypeError
。- message¶
建構函式的
msg
引數。這是一個唯讀的屬性。
- exceptions¶
指定給建構函式
excs
序列中的例外組成的元組。這是一個唯讀的屬性。
- subgroup(condition)¶
回傳只包含從現有群組比對到 condition 的例外的例外群組,或者當結果為空時回傳
None
。條件可以是一個函式,接受一個例外並對那些應該要在子群組裡的例外回傳 true,或者可以是一個例外類型或例外類型的元組,並使用與
except
子句所使用的相同檢查來檢查是否有比對到。現有例外的巢狀結構會保留在結果裡,其
message
、__traceback__
、__cause__
、__context__
及__notes__
欄位的值也一樣。空的巢狀群組會從結果裡排除。條件會對巢狀例外群組裡的所有例外做檢查,包括頂層及任何巢狀的例外群組。如果條件對這樣的例外群組為 true,它會被完整包含在結果裡。
- split(condition)¶
像
subgroup()
一樣,但回傳一對(match, rest)
,其中match
是subgroup(condition)
而rest
是剩下沒有比對到的部分。
- derive(excs)¶
回傳有相同
message
但將例外包裝在excs
的例外群組。此方法被
subgroup()
及split()
使用,被用來在各種情境下拆分例外群組。子類別需要覆寫它來讓subgroup()
及split()
回傳子類別而不是ExceptionGroup
的實例。subgroup()
及split()
會從原始的例外群組複製__traceback__
、__cause__
、__context__
和__notes__
欄位到derive()
所回傳的例外群組上,因此這些欄位不需要被derive()
更新。>>> class MyGroup(ExceptionGroup): ... def derive(self, excs): ... return MyGroup(self.message, excs) ... >>> e = MyGroup("eg", [ValueError(1), TypeError(2)]) >>> e.add_note("a note") >>> e.__context__ = Exception("context") >>> e.__cause__ = Exception("cause") >>> try: ... raise e ... except Exception as e: ... exc = e ... >>> match, rest = exc.split(ValueError) >>> exc, exc.__context__, exc.__cause__, exc.__notes__ (MyGroup('eg', [ValueError(1), TypeError(2)]), Exception('context'), Exception('cause'), ['a note']) >>> match, match.__context__, match.__cause__, match.__notes__ (MyGroup('eg', [ValueError(1)]), Exception('context'), Exception('cause'), ['a note']) >>> rest, rest.__context__, rest.__cause__, rest.__notes__ (MyGroup('eg', [TypeError(2)]), Exception('context'), Exception('cause'), ['a note']) >>> exc.__traceback__ is match.__traceback__ is rest.__traceback__ True
需注意
BaseExceptionGroup
定義了__new__()
,因此需要不同建構函式簽名的子類別需要覆寫它而不是__init__()
。例如下面定義了一個例外群組子類別接受 exit_code 並從中建構群組的訊息。:class Errors(ExceptionGroup): def __new__(cls, errors, exit_code): self = super().__new__(Errors, f"exit code: {exit_code}", errors) self.exit_code = exit_code return self def derive(self, excs): return Errors(excs, self.exit_code)
像
ExceptionGroup
一樣,任何BaseExceptionGroup
的子類別且也是Exception
的子類別只能包裝Exception
的實例。在 3.11 版被加入.
例外階層¶
內建例外的類別階層如下:
BaseException
├── BaseExceptionGroup
├── GeneratorExit
├── KeyboardInterrupt
├── SystemExit
└── Exception
├── ArithmeticError
│ ├── FloatingPointError
│ ├── OverflowError
│ └── ZeroDivisionError
├── AssertionError
├── AttributeError
├── BufferError
├── EOFError
├── ExceptionGroup [BaseExceptionGroup]
├── ImportError
│ └── ModuleNotFoundError
├── LookupError
│ ├── IndexError
│ └── KeyError
├── MemoryError
├── NameError
│ └── UnboundLocalError
├── OSError
│ ├── BlockingIOError
│ ├── ChildProcessError
│ ├── ConnectionError
│ │ ├── BrokenPipeError
│ │ ├── ConnectionAbortedError
│ │ ├── ConnectionRefusedError
│ │ └── ConnectionResetError
│ ├── FileExistsError
│ ├── FileNotFoundError
│ ├── InterruptedError
│ ├── IsADirectoryError
│ ├── NotADirectoryError
│ ├── PermissionError
│ ├── ProcessLookupError
│ └── TimeoutError
├── ReferenceError
├── RuntimeError
│ ├── NotImplementedError
│ └── RecursionError
├── StopAsyncIteration
├── StopIteration
├── SyntaxError
│ └── IndentationError
│ └── TabError
├── SystemError
├── TypeError
├── ValueError
│ └── UnicodeError
│ ├── UnicodeDecodeError
│ ├── UnicodeEncodeError
│ └── UnicodeTranslateError
└── Warning
├── BytesWarning
├── DeprecationWarning
├── EncodingWarning
├── FutureWarning
├── ImportWarning
├── PendingDeprecationWarning
├── ResourceWarning
├── RuntimeWarning
├── SyntaxWarning
├── UnicodeWarning
└── UserWarning