內建的例外

在 Python 中,所有例外必須是從 BaseException 衍生的類別的實例。在陳述式 try 搭配 except 子句裡提到一個特定的類別時,那個子句也會處理任何從該類別衍生的例外類別(但不會處理該類別衍生自的例外類別)。兩個不是由子類別關係關聯起來的例外類別永遠不相等,就算它們有相同的名稱也是如此。

此章節裡列出的內建例外可以從直譯器或內建函式產生。除了特別提到的地方之外,它們會有一個關聯值表示錯誤發生的詳細原因。這可能是一個字串,或者是一些資訊項目組成的元組(例如一個錯誤代碼及一個解釋該代碼的字串)。這個關聯值通常當作引數傳遞給例外類別的建構函式。

使用者的程式碼可以引發內建例外。這可以用來測試例外處理器或者用來回報一個錯誤條件,就像直譯器會引發相同例外的情況;但需要注意的是沒有任何方式可以避免使用者的程式碼引發不適當的錯誤。

可以從內建的例外類別定義新的例外子類別;程式設計師被鼓勵從 Exception 類別或其子類別衍生新的例外,而不是從 BaseException 來衍生。更多關於定義例外的資訊可以在 Python 教學中的使用者自定的例外裡取得。

例外的情境

三個例外物件上的屬性提供關於引發此例外的情境的資訊:

BaseException.__context__
BaseException.__cause__
BaseException.__suppress_context__

當引發一個新的例外而同時有另一個例外已經正在被處理時,這個新例外的 __context__ 屬性會自動被設成那個已處理的例外。當使用 exceptfinally 子句或 with 陳述式的時候例外會被處理。

這個隱含的例外情境可以透過使用 from 搭配 raise 來補充明確的原因:

raise new_exc from original_exc

from 後面的運算式必須是一個例外或 None。它將會被設定成所引發例外的 __cause__。設定 __cause__ 也隱含地設定 __suppress_context__ 屬性為 True,因此使用 raise new_exc from None 實際上會以新的例外取代舊的例外以利於顯示(例如轉換 KeyErrorAttributeError),同時保持舊的例外可以透過 __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(),會回傳實例的引數的表示,或者沒有引數的時候會回傳空字串。

args

提供給該例外建構函式的引數元組。一些內建的例外(像是 OSError)預期接受特定數量的引數並賦予該元組的每一個元素一個特別的意義,其他例外則通常用一個提供錯誤訊息的單一字串來呼叫。

with_traceback(tb)

此方法設定 tb 為該例外的新的回溯並回傳該例外物件。在 PEP 3134 的例外連鎖功能變得可用之前,此方法曾被更普遍使用。下面的範例顯示我們如何將 SomeException 的實例轉換為 OtherException 的實例同時保留回溯。一旦被引發,目前的 frame 會被加進 OtherException 的回溯,就像原來 SomeException 的回溯會發生的一樣,我們允許它被傳遞給呼叫者:

try:
    ...
except SomeException:
    tb = sys.exception().__traceback__
    raise OtherException(...).with_traceback(tb)
__traceback__

可寫入的欄位,儲存關聯到該例外的回溯物件。也可以參考 raise 语句

add_note(note)

新增字串 note 到例外的備註,在標準的回溯裡,備註出現在例外字串的後面。如果 note 不是字串則引發 TypeError

在 3.11 版新加入.

__notes__

該例外的備註串列,使用 add_note() 來新增。此屬性在 add_note() 被呼叫的時候建立。

在 3.11 版新加入.

exception Exception

所有內建、非系統退出 (non-system-exiting) 的例外都衍生自此類別。所有使用者定義的例外應該也要衍生自此類別。

exception ArithmeticError

各種運算錯誤所引發的那些內建例外:OverflowErrorZeroDivisionErrorFloatingPointError 的基底類別。

exception BufferError

緩衝 (buffer) 相關的操作無法被執行時會引發此例外。

exception LookupError

當使用在對映或序列上的鍵或索引是無效的時候所引發的例外:IndexErrorKeyError 的基底類別。這可以被 codecs.lookup() 直接引發。

實體例外

以下的例外是通常會被引發的例外。

exception AssertionError

assert 陳述式失敗的時候被引發。

exception AttributeError

當屬性參照(參考 属性引用)或賦值失敗的時候被引發。(當物件根本不支援屬性參照或屬性賦值的時候,TypeError 會被引發。)

nameobj 屬性可以使用建構函式的僅限關鍵字 (keyword-only) 引數來設定。當被設定的時候,它們分別代表被嘗試存取的屬性名稱以及被以該屬性存取的物件。

在 3.10 版的變更: 新增 nameobj 屬性。

exception EOFError

input() 函式在沒有讀到任何資料而到達檔案結尾 (end-of-file, EOF) 條件的時候被引發。(注意:io.IOBase.read()io.IOBase.readline() 方法當達到 EOF 時會回傳空字串。)

exception FloatingPointError

目前沒有被使用。

exception GeneratorExit

generatorcoroutine 被關閉的時候被引發;參考 generator.close()coroutine.close()。此例外直接繼承自 BaseException 而不是 Exception,因為技術上來說這不是一個錯誤。

exception ImportError

import 陳述式嘗試載入模組遇到問題的時候會被引發。當 from import 裡的 “from list” 包含找不到的名稱時也會被引發。

可選的僅限關鍵字引數 namepath 設定對應的屬性:

name

嘗試引入 (import) 的模組名稱。

path

觸發此例外的任何檔案的路徑。

在 3.3 版的變更: 新增 namepath 屬性。

exception ModuleNotFoundError

ImportError 的子類別,當模組不能被定位的時候會被 import 所引發。當在 sys.modules 裡找到 None 時也會被引發。

在 3.6 版新加入.

exception IndexError

當序列的索引超出範圍的時候會被引發。(切片索引 (slice indices) 會默默地被截短使其能落在允許的範圍內;如果索引不是整數,TypeError 會被引發。)

exception KeyError

當對映(字典)的鍵無法在已存在的鍵的集合中被找到時會被引發。

exception KeyboardInterrupt

當使用者輸入中斷鍵 (interrupt key)(一般來說是 Control-CDelete)時會被引發。在執行過程中,會定期檢查是否產生中斷。此例外繼承自 BaseException 以防止意外地被捕捉 Exception 的程式碼所捕捉,而因此讓直譯器無法結束。

備註

捕捉 KeyboardInterrupt 需要特殊的考量。因為它可以在無法預期的時間點被引發,可能在某些情況下讓正在跑的程式處在一個不一致的狀態。一般來說最好讓 KeyboardInterrupt 越快結束程式越好,或者完全避免引發它。(參考 有关信号处理句柄和异常的注释。)

exception MemoryError

當一個操作用光了記憶體但情況還可能被修復 (rescued)(透過刪除一些物件)的時候被引發。關聯的值是一個字串,表示什麼類型的(內部)操作用光了記憶體。需注意的是因為底層的記憶體管理架構(C 的 malloc() 函式),直譯器可能無法總是完整地從該情況中修復;僅管如此,它還是引發例外以讓堆疊回溯可以被印出,以防原因出在失控的程式。

exception NameError

當找不到本地或全域的名稱時會被引發。這只應用在不合格的名稱 (unqualified name) 上。關聯的值是一個錯誤訊息,包含那個無法被找到的名稱。

name 屬性可以使用僅限關鍵字引數來設定到建構函式。當被設定的時候它代表被嘗試存取的變數名稱。

在 3.10 版的變更: 新增 name 屬性。

exception NotImplementedError

此异常派生自 RuntimeError。 在用户自定义的基类中,抽象方法应当在其要求所派生类重写该方法,或是在其要求所开发的类提示具体实现尚待添加时引发此异常。

備註

它不应当用来表示一个运算符或方法根本不能被支持 -- 在此情况下应当让特定运算符 / 方法保持未定义,或者在子类中将其设为 None

備註

NotImplementedErrorNotImplemented 不能互换,尽管它们的名称和用途相似。有关何时使用的详细信息,请参阅 NotImplemented

exception OSError([arg])
exception OSError(errno, strerror[, filename[, winerror[, filename2]]])

此异常在一个系统函数返回系统相关的错误时将被引发,此类错误包括 I/O 操作失败例如 "文件未找到" 或 "磁盘已满" 等(不包括非法参数类型或其他偶然性错误)。

构造器的第二种形式可设置如下所述的相应属性。 如果未指定这些属性则默认为 None。 为了能向下兼容,如果传入了三个参数,则 args 属性将仅包含由前两个构造器参数组成的 2 元组。

构造器实际返回的往往是 OSError 的某个子类,如下文 OS exceptions 中所描述的。 具体的子类取决于最终的 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.errormmap.error 已被合并到 OSError,构造器可能返回其中一个子类。

在 3.4 版的變更: filename 属性现在是传给函数的原始文件名,而不是基于 filesystem encoding and error handler 进行编码或解码之后的名称。 此外,还添加了 filename2 构造器参数和属性。

exception OverflowError

当算术运算的结果大到无法表示时将被引发。 这对整数来说不可能发生(宁可引发 MemoryError 也不会放弃尝试)。 但是出于历史原因,有时也会在整数超出要求范围的情况下引发 OverflowError。 因为在 C 中缺少对浮点异常处理的标准化,大多数浮点运算都不会做检查。

exception RecursionError

此异常派生自 RuntimeError。 它会在解释器检测发现超过最大递归深度 (参见 sys.getrecursionlimit()) 时被引发。

在 3.5 版新加入: 在此之前将只引发 RuntimeError

exception ReferenceError

此异常将在使用 weakref.proxy() 函数所创建的弱引用来访问该引用的某个已被作为垃圾回收的属性时被引发。 有关弱引用的更多信息请参阅 weakref 模块。

exception RuntimeError

当检测到一个不归属于任何其他类别的错误时将被引发。 关联的值是一个指明究竟发生了什么问题的字符串。

exception StopIteration

由内置函数 next()iterator__next__() 方法所引发,用来表示该迭代器不能产生下一项。

value

该异常对象只有一个属性 value,它在构造该异常时作为参数给出,默认值为 None

当一个 generatorcoroutine 函数返回时,将引发一个新的 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() 只返回错误消息。 错误详情为一个元组,其成员也可在单独的属性中分别获取。

filename

发生语法错误所在文件的名称。

lineno

发生错误所在文件中的行号。 行号索引从 1 开始:文件中首行的 lineno 为 1。

offset

发生错误所在文件中的列号。 列号索引从 1 开始:行中首个字符的 offset 为 1。

text

错误所涉及的源代码文本。

end_lineno

发生的错误在文件中的末尾行号。 这个索引是从 1 开始的:文件中首行的 lineno 为 1。

end_offset

发生的错误在文件中的末尾列号。 这个索引是从 1 开始:行中首个字符的 offset 为 1。

对于 f-字符串字段中的错误,消息会带有 "f-string: " 前缀并且其位置是基于替换表达式构建的文本中的位置。 例如,编译 f'Bad {a b} field' 将产生这样的 args 属性: ('f-string: ...', ('', 1, 2, '(a b)n', 1, 5))。

在 3.10 版的變更: 新增 end_linenoend_offset 屬性。

exception IndentationError

与不正确的缩进相关的语法错误的基类。 这是 SyntaxError 的一个子类。

exception TabError

当缩进包含对制表符和空格符不一致的使用时将被引发。 这是 IndentationError 的一个子类。

exception SystemError

当解释器发现内部错误,但情况看起来尚未严重到要放弃所有希望时将被引发。 关联的值是一个指明发生了什么问题的字符串(表示为低层级的符号)。

你应当将此问题报告给你所用 Python 解释器的作者或维护人员。 请确认报告 Python 解释器的版本号 (sys.version; 它也会在交互式 Python 会话开始时被打印出来),具体的错误消息(异常所关联的值)以及可能触发该错误的程序源码。

exception SystemExit

此异常由 sys.exit() 函数引发。 它继承自 BaseException 而不是 Exception 以确保不会被处理 Exception 的代码意外捕获。 这允许此异常正确地向上传播并导致解释器退出。 如果它未被处理,则 Python 解释器就将退出;不会打印任何栈回溯信息。 构造器接受的可选参数与传递给 sys.exit() 的相同。 如果该值为一个整数,则它指明系统退出状态码(会传递给 C 的 exit() 函数);如果该值为 None,则退出状态码为零;如果该值为其他类型(例如字符串),则会打印对象的值并将退出状态码设为一。

sys.exit() 的调用会被转换为一个异常以便能执行清理处理程序 (try 语句的 finally 子句),并且使得调试器可以执行一段脚本而不必冒失去控制的风险。 如果绝对确实地需要立即退出(例如在调用 os.fork() 之后的子进程中)则可使用 os._exit().

code

传给构造器的退出状态码或错误信息(默认为 None。)

exception TypeError

当一个操作或函数被应用于类型不适当的对象时将被引发。 关联的值是一个字符串,给出有关类型不匹配的详情。

此异常可以由用户代码引发,以表明尝试对某个对象进行的操作不受支持也不应当受支持。 如果某个对象应当支持给定的操作但尚未提供相应的实现,所要引发的适当异常应为 NotImplementedError

传入参数的类型错误 (例如在要求 int 时却传入了 list) 应当导致 TypeError,但传入参数的值错误 (例如传入要求范围之外的数值) 则应当导致 ValueError

exception UnboundLocalError

当在函数或方法中对某个局部变量进行引用,但该变量并未绑定任何值时将被引发。 此异常是 NameError 的一个子类。

exception UnicodeError

当发生与 Unicode 相关的编码或解码错误时将被引发。 此异常是 ValueError 的一个子类。

UnicodeError 具有一些描述编码或解码错误的属性。 例如 err.object[err.start:err.end] 会给出导致编解码器失败的特定无效输入。

encoding

引发错误的编码名称。

reason

描述特定编解码器错误的字符串。

object

编解码器试图要编码或解码的对象。

start

object 中无效数据的开始位置索引。

end

object 中无效数据的末尾位置索引(不含)。

exception UnicodeEncodeError

当在编码过程中发生与 Unicode 相关的错误时将被引发。 此异常是 UnicodeError 的一个子类。

exception UnicodeDecodeError

当在解码过程中发生与 Unicode 相关的错误时将被引发。 此异常是 UnicodeError 的一个子类。

exception UnicodeTranslateError

在转写过程中发生与 Unicode 相关的错误时将被引发。 此异常是 UnicodeError 的一个子类。

exception ValueError

当操作或函数接收到具有正确类型但值不适合的参数,并且情况不能用更精确的异常例如 IndexError 来描述时将被引发。

exception ZeroDivisionError

当除法或取余运算的第二个参数为零时将被引发。 关联的值是一个字符串,指明操作数和运算的类型。

下列异常被保留以与之前的版本相兼容;从 Python 3.3 开始,它们都是 OSError 的别名。

exception EnvironmentError
exception IOError
exception WindowsError

限在 Windows 中可用。

OS 异常

下列异常均为 OSError 的子类,它们将根据系统错误代码被引发。

exception BlockingIOError

当一个操作将在设置为非阻塞操作的对象(例如套接字)上发生阻塞时将被引发。 对应于 errno EAGAIN, EALREADY, EWOULDBLOCKEINPROGRESS

除了 OSError 已有的属性,BlockingIOError 还有一个额外属性:

characters_written

一个整数,表示在被阻塞前已写入到流的字符数。 当使用来自 io 模块的带缓冲 I/O 类时此属性可用。

exception ChildProcessError

当一个子进程上的操作失败时将被引发。 对应于 errno ECHILD

exception ConnectionError

与连接相关问题的基类。

其子类有 BrokenPipeError, ConnectionAbortedError, ConnectionRefusedErrorConnectionResetError

exception BrokenPipeError

ConnectionError 的子类,当试图写入一个管道而其另一端已关闭,或者试图写入一个套接字而其已关闭写入时将被引发。 对应于 errno EPIPEESHUTDOWN

exception ConnectionAbortedError

ConnectionError 的子类,当一个连接尝试被对端中止时将被引发。 对应于 errno ECONNABORTED

exception ConnectionRefusedError

ConnectionError 的子类,当一个连接尝试被对端拒绝时将被引发。 对应于 errno ECONNREFUSED

exception ConnectionResetError

ConnectionError 的子类,当一个连接尝试被对端重置时将被引发。 对应于 errno ECONNRESET

exception FileExistsError

当试图创建一个已存在的文件或目录时将被引发。 对应于 errno EEXIST

exception FileNotFoundError

当所请求的文件或目录不存在时将被引发。 对应于 errno ENOENT

exception InterruptedError

当一个系统调用被传入的信号中断时将被引发。 对应于 errno EINTR

在 3.5 版的變更: 当系统调用被某个信号中断时,Python 现在会重试系统调用,除非该信号的处理程序引发了其它异常 (原理参见 PEP 475) 而不是引发 InterruptedError

exception IsADirectoryError

当请求对一个目录执行文件操作 (如 os.remove()) 时将被引发。 对应于 errno EISDIR

exception NotADirectoryError

当请求对一个非目录执行目录操作 (如 os.listdir()) 时将被引发。 在大多数 POSIX 平台上,它还可能在某个操作试图将一个非目录作为目录打开或遍历时被引发。 对应于 errno ENOTDIR

exception PermissionError

当在没有足够访问权限的情况下试图运行某个操作时将被引发 —— 例如文件系统权限。 对应于 errno EACCES, EPERMENOTCAPABLE

在 3.11.1 版的變更: WASI 的 ENOTCAPABLE 现在被映射至 PermissionError

exception ProcessLookupError

当给定的进程不存在时将被引发。 对应于 errno ESRCH

exception TimeoutError

当一个系统函数在系统层级发生超时的情况下将被引发。 对应于 errno ETIMEDOUT

在 3.3 版新加入: 添加了以上所有 OSError 的子类。

也參考

PEP 3151 - 重写 OS 和 IO 异常的层次结构

警告

下列异常被用作警告类别;请参阅 警告类别 文档了解详情。

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 BytesWarning

bytesbytearray 相关的警告的基类。

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

BaseExceptionGroup 构造器返回一个 ExceptionGroup 而不是 BaseExceptionGroup,如果所包含的全部异常都是 Exception 的实例的话,因此它可以被用来制造自动化的选择。 在另一方面,ExceptionGroup 构造器则会引发 TypeError,如果所包含的任何异常不是 Exception 的子类的话。

message

传给构造器的 msg 参数。 这是一个只读属性。

exceptions

传给构造器的 excs 序列中的由异常组成的元组。 这是一个只读属性。

subgroup(condition)

返回一个只包含来自当前组的匹配 condition 的异常的异常组,或者如果结果为空则返回 None

condition 参数可以是一个接受异常并为应当纳入子分组的异常返回真值的函数,或者也可以是一个异常类型或一个由异常类型组成的元组,用来通过与 except 子句所用的相同检测来检测是否匹配。

当前异常的嵌套结构会在结果中保留,就如其 message, __traceback__, __cause__, __context____notes__ 字段的值一样。 空的嵌套组会在结果中被略去。

条件检测会针对嵌套异常组中的所有异常执行,包括最高层级的和任何嵌套的异常组。 如果针对此类异常组的条件为真值,它将被完整包括在结果中。

split(condition)

类似于 subgroup(),但将返回 (match, rest) 对,其中 matchsubgroup(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