异常处理 — Python 文档

来自菜鸟教程
Python/docs/3.9/c-api/exceptions
跳转至:导航、​搜索

异常处理

本章中描述的函数将让您处理和引发 Python 异常。 了解 Python 异常处理的一些基础知识很重要。 它的工作方式有点像 POSIX errno 变量:上次发生的错误有一个全局指示器(每个线程)。 大多数 C API 函数在成功时不会清除它,但会设置它以指示失败时错误的原因。 大多数 C API 函数也返回一个错误指示符,通常是 NULL 如果它们应该返回一个指针,或者 -1 如果它们返回一个整数(例外:PyArg_*函数返回 1 表示成功,返回 0 表示失败)。

具体来说,错误指示器由三个对象指针组成:异常类型、异常值和回溯对象。 如果未设置,这些指针中的任何一个都可以是 NULL(尽管禁止某些组合,例如,如果异常类型是 [X175X,则不能有非 NULL 回溯) ])。

当一个函数因为它调用的某个函数失败而必须失败时,它通常不设置错误指示器; 它调用的函数已经设置了它。 它负责处理错误和清除异常,或者在清理它持有的任何资源(例如对象引用或内存分配)后返回; 如果它不准备处理错误,它应该 not 继续正常。 如果由于错误而返回,则向调用者表明已设置错误很重要。 如果错误没有得到处理或小心传播,对 Python/C API 的额外调用可能不会按预期运行,并且可能会以神秘的方式失败。

笔记

错误指示符是 不是 sys.exc_info() 的结果。 前者对应于尚未捕获的异常(因此仍在传播),而后者在捕获后返回异常(因此已停止传播)。


打印和清算

void PyErr_Clear()
清除错误指示器。 如果未设置错误指示器,则没有效果。
void PyErr_PrintEx(int set_sys_last_vars)

将标准回溯打印到 sys.stderr 并清除错误指示器。 除非 错误是 SystemExit,在这种情况下,不会打印回溯,Python 进程将以 SystemExit 实例指定的错误代码退出。

设置错误指示器时,仅调用此函数 ' 。 否则会导致致命错误!

如果 set_sys_last_vars 不为零,则变量 sys.last_typesys.last_valuesys.last_traceback 将被设置为类型、值和打印异常的回溯,分别。

void PyErr_Print()
PyErr_PrintEx(1) 的别名。
void PyErr_WriteUnraisable(PyObject *obj)

使用当前异常和 obj 参数调用 sys.unraisablehook()

当设置了异常但解释器不可能实际引发异常时,此实用程序函数会向 sys.stderr 打印一条警告消息。 例如,在 __del__() 方法中发生异常时使用。

使用单个参数 obj 调用该函数,该参数标识发生不可引发异常的上下文。 如果可能,obj 的 repr 将打印在警告消息中。

调用此函数时必须设置异常。


引发异常

这些函数帮助您设置当前线程的错误指示器。 为方便起见,其中一些函数将始终返回 NULL 指针以用于 return 语句。

void PyErr_SetString(PyObject *type, const char *message)
这是设置错误指示器的最常用方法。 第一个参数指定异常类型; 它通常是标准例外之一,例如 PyExc_RuntimeError。 你不需要增加它的引用计数。 第二个参数是错误信息; 它是从 'utf-8' 解码的。
void PyErr_SetObject(PyObject *type, PyObject *value)
此函数类似于 PyErr_SetString() 但允许您为异常的“值”指定任意 Python 对象。
PyObject *PyErr_Format(PyObject *exception, const char *format, ...)
该函数设置错误指示器并返回NULLexception 应该是一个 Python 异常类。 format 和后续参数帮助格式化错误信息; 它们与 PyUnicode_FromFormat() 具有相同的含义和值。 format 是一个 ASCII 编码的字符串。
PyObject *PyErr_FormatV(PyObject *exception, const char *format, va_list vargs)

PyErr_Format() 相同,但采用 va_list 参数而不是可变数量的参数。

3.5 版中的新功能。

void PyErr_SetNone(PyObject *type)
这是 PyErr_SetObject(type, Py_None) 的简写。
int PyErr_BadArgument()
这是 PyErr_SetString(PyExc_TypeError, message) 的简写,其中 message 表示使用非法参数调用了内置操作。 它主要供内部使用。
PyObject *PyErr_NoMemory()
这是 PyErr_SetNone(PyExc_MemoryError) 的简写; 它返回 NULL,因此对象分配函数可以在内存不足时写入 return PyErr_NoMemory();
PyObject *PyErr_SetFromErrno(PyObject *type)
这是一个方便的函数,可以在 C 库函数返回错误并设置 C 变量 errno 时引发异常。 它构造一个元组对象,其第一项是整数 errno 值,第二项是相应的错误消息(从 strerror() 中获取),然后调用 PyErr_SetObject(type, object)。 在 Unix 上,当 errno 值为 EINTR 时,表示系统调用中断,这将调用 PyErr_CheckSignals(),如果设置了错误指示符,则将其设置为那。 该函数始终返回 NULL,因此系统调用周围的包装函数可以在系统调用返回错误时写入 return PyErr_SetFromErrno(type);
PyObject *PyErr_SetFromErrnoWithFilenameObject(PyObject *type, PyObject *filenameObject)
PyErr_SetFromErrno() 类似,附加的行为是如果 filenameObject 不是 NULL,它会作为一个传递给 type 的构造函数第三个参数。 在 OSError 异常的情况下,这用于定义异常实例的 filename 属性。
PyObject *PyErr_SetFromErrnoWithFilenameObjects(PyObject *type, PyObject *filenameObject, PyObject *filenameObject2)

类似于 PyErr_SetFromErrnoWithFilenameObject(),但需要第二个文件名对象,用于在需要两个文件名的函数失败时引发错误。

3.4 版中的新功能。

PyObject *PyErr_SetFromErrnoWithFilename(PyObject *type, const char *filename)
类似于 PyErr_SetFromErrnoWithFilenameObject(),但文件名以 C 字符串形式给出。 filename 从文件系统编码 (os.fsdecode()) 解码。
PyObject *PyErr_SetFromWindowsErr(int ierr)
这是一个方便的函数来引发 WindowsError。 如果使用 0ierr 调用,则使用调用 GetLastError() 返回的错误代码。 它调用 Win32 函数 FormatMessage() 来检索由 ierrGetLastError() 给出的错误代码的 Windows 描述,然后构造一个元组对象,其第一项是 ierr 值,其第二项是对应的错误信息(取自 FormatMessage()),然后调用 PyErr_SetObject(PyExc_WindowsError, object)。 此函数始终返回 NULL
PyObject *PyErr_SetExcFromWindowsErr(PyObject *type, int ierr)
类似于 PyErr_SetFromWindowsErr(),附加参数指定要引发的异常类型。
PyObject *PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename)
类似于 PyErr_SetFromWindowsErrWithFilenameObject(),但文件名以 C 字符串形式给出。 filename 从文件系统编码 (os.fsdecode()) 解码。
PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename)
PyErr_SetFromWindowsErrWithFilenameObject() 类似,附加参数指定要引发的异常类型。
PyObject *PyErr_SetExcFromWindowsErrWithFilenameObjects(PyObject *type, int ierr, PyObject *filename, PyObject *filename2)

类似于 PyErr_SetExcFromWindowsErrWithFilenameObject(),但接受第二个文件名对象。

3.4 版中的新功能。

PyObject *PyErr_SetExcFromWindowsErrWithFilename(PyObject *type, int ierr, const char *filename)
类似于 PyErr_SetFromWindowsErrWithFilename(),附加参数指定要引发的异常类型。
PyObject *PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)

这是一个提高 ImportError 的便利函数。 msg 将被设置为异常的消息字符串。 namepath,两者都可以是NULL,将被设置为ImportError各自的namepath 属性。

3.3 版中的新功能。

void PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)

为当前异常设置文件、行和偏移量信息。 如果当前异常不是 SyntaxError,则设置附加属性,使异常打印子系统认为异常是 SyntaxError

3.4 版中的新功能。

void PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)

类似于 PyErr_SyntaxLocationObject(),但 filename 是从文件系统编码 (os.fsdecode()) 解码的字节串。

3.2 版中的新功能。

void PyErr_SyntaxLocation(const char *filename, int lineno)
类似于 PyErr_SyntaxLocationEx(),但省略了 col_offset 参数。
void PyErr_BadInternalCall()
这是 PyErr_SetString(PyExc_SystemError, message) 的简写,其中 message 表示内部操作(例如 一个 Python/C API 函数)被非法参数调用。 它主要供内部使用。


发出警告

使用这些函数从 C 代码发出警告。 它们反映了 Python warnings 模块导出的类似函数。 他们通常会向 sys.stderr 打印警告消息; 然而,也有可能用户已指定将警告转换为错误,在这种情况下,它们将引发异常。 由于警告机制的问题,这些函数也可能引发异常。 如果未引发异常,则返回值为 0,如果引发异常,则返回值为 -1。 (无法确定是否实际打印了警告消息,也无法确定异常的原因是什么;这是故意的。)如果引发异常,调用者应该进行正常的异常处理(例如, Py_DECREF() 拥有引用并返回错误值)。

int PyErr_WarnEx(PyObject *category, const char *message, Py_ssize_t stack_level)

发出警告消息。 category 参数是一个警告类别(见下文)或 NULLmessage 参数是一个 UTF-8 编码的字符串。 stack_level 是一个正数,给出了堆栈帧的数量; 警告将从该堆栈帧中当前正在执行的代码行发出。 stack_level 为 1 是调用 PyErr_WarnEx() 的函数,2 是上面的函数,依此类推。

警告类别必须是 PyExc_Warning 的子类; PyExc_WarningPyExc_Exception的子类; 默认警告类别为 PyExc_RuntimeWarning。 标准 Python 警告类别可用作全局变量,其名称在 标准警告类别 中枚举。

有关警告控制的信息,请参阅命令行文档中 warnings 模块和 -W 选项的文档。 没有用于警告控制的 C API。

PyObject *PyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg, PyObject *name, PyObject *path)

很像 PyErr_SetImportError() 但这个函数允许指定 ImportError 的子类来引发。

3.6 版中的新功能。

int PyErr_WarnExplicitObject(PyObject *category, PyObject *message, PyObject *filename, int lineno, PyObject *module, PyObject *registry)

发出警告消息,明确控制所有警告属性。 这是 Python 函数 warnings.warn_explicit() 的简单包装,请参阅此处了解更多信息。 moduleregistry 参数可以设置为 NULL 以获得那里描述的默认效果。

3.4 版中的新功能。

int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry)
PyErr_WarnExplicitObject() 类似,除了 messagemodule 是 UTF-8 编码的字符串,而 filename 是从文件系统编码中解码出来的( os.fsdecode())。
int PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, const char *format, ...)

函数类似于 PyErr_WarnEx(),但使用 PyUnicode_FromFormat() 来格式化警告消息。 format 是一个 ASCII 编码的字符串。

3.2 版中的新功能。

int PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level, const char *format, ...)

函数类似于 PyErr_WarnFormat(),但 categoryResourceWarning 并将 source 传递给 warnings.WarningMessage()

3.6 版中的新功能。


查询错误指示符

PyObject *PyErr_Occurred()

测试是否设置了错误指示灯。 如果设置,则返回异常 type(最后一次调用 PyErr_Set* 函数或 PyErr_Restore() 的第一个参数)。 如果未设置,则返回 NULL。 您不拥有对返回值的引用,因此您不需要 Py_DECREF() 它。

调用者必须持有 GIL。

笔记

不要将返回值与特定异常进行比较; 使用 PyErr_ExceptionMatches() 代替,如下所示。 (比较可能很容易失败,因为异常可能是一个实例而不是一个类,在类异常的情况下,或者它可能是预期异常的子类。)

int PyErr_ExceptionMatches(PyObject *exc)
相当于 PyErr_GivenExceptionMatches(PyErr_Occurred(), exc)。 这应该只在实际设置异常时调用; 如果没有引发异常,则会发生内存访问冲突。
int PyErr_GivenExceptionMatches(PyObject *given, PyObject *exc)
如果 given 异常与 exc 中的异常类型匹配,则返回 true。 如果 exc 是一个类对象,当 given 是一个子类的实例时,这也返回真。 如果 exc 是元组,则元组中的所有异常类型(以及子元组中的递归)都将搜索匹配项。
void PyErr_Fetch(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)

将错误指示符检索到三个传递地址的变量中。 如果未设置错误指示器,请将所有三个变量设置为 NULL。 如果设置了它,它将被清除,并且您拥有对检索到的每个对象的引用。 即使类型对象不是,值和回溯对象也可能是 NULL

笔记

该函数通常只被需要捕获异常的代码或需要临时保存和恢复错误指示器的代码使用,例如:

{
   PyObject *type, *value, *traceback;
   PyErr_Fetch(&type, &value, &traceback);

   /* ... code that might produce other errors ... */

   PyErr_Restore(type, value, traceback);
}
void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)

从三个对象设置错误指示器。 如果错误指示器已设置,则首先将其清除。 如果对象为NULL,则清除错误指示符。 不要传递 NULL 类型和非 NULL 值或回溯。 异常类型应该是一个类。 不要传递无效的异常类型或值。 (违反这些规则会在以后导致一些微妙的问题。)这个调用会带走对每个对象的引用:在调用之前你必须拥有对每个对象的引用,在调用之后你不再拥有这些引用。 (如果您不明白这一点,请不要使用此功能。 我警告过你。)

笔记

该函数通常只用于需要临时保存和恢复错误指示器的代码。 使用 PyErr_Fetch() 保存当前错误指标。

void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)

在某些情况下,下面的 PyErr_Fetch() 返回的值可以是“非规范化的”,这意味着 *exc 是一个类对象但 *val 不是相同的实例班级。 在这种情况下,此函数可用于实例化类。 如果这些值已经标准化,则什么也不会发生。 实施延迟归一化以提高性能。

笔记

此函数 不会 隐式设置异常值的 __traceback__ 属性。 如果需要适当地设置回溯,则需要以下附加代码段:

if (tb != NULL) {
  PyException_SetTraceback(val, tb);
}
void PyErr_GetExcInfo(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)

sys.exc_info() 中检索异常信息。 这是指 已捕获 的异常,而不是新引发的异常。 返回三个对象的新引用,其中任何一个都可以是 NULL。 不修改异常信息状态。

笔记

想要处理异常的代码通常不使用此函数。 相反,它可以在代码需要临时保存和恢复异常状态时使用。 使用 PyErr_SetExcInfo() 恢复或清除异常状态。

3.3 版中的新功能。

void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)

设置异常信息,如从 sys.exc_info() 所知。 这是指 已捕获 的异常,而不是新引发的异常。 此函数窃取参数的引用。 要清除异常状态,请为所有三个参数传递 NULL。 有关这三个参数的一般规则,请参阅 PyErr_Restore()

笔记

想要处理异常的代码通常不使用此函数。 相反,它可以在代码需要临时保存和恢复异常状态时使用。 使用 PyErr_GetExcInfo() 读取异常状态。

3.3 版中的新功能。


信号处理

int PyErr_CheckSignals()
此函数与 Python 的信号处理交互。 它检查信号是否已发送到进程,如果是,则调用相应的信号处理程序。 如果支持 signal 模块,则可以调用用 Python 编写的信号处理程序。 在所有情况下,SIGINT 的默认效果是引发 KeyboardInterrupt 异常。 如果引发异常,则设置错误指示器并且函数返回 -1; 否则函数返回 0。 如果先前已设置,错误指示器可能会或可能不会被清除。
void PyErr_SetInterrupt()

模拟 SIGINT 信号到达的效果。 下次调用 PyErr_CheckSignals() 时,将调用 SIGINT 的 Python 信号处理程序。

如果 SIGINT 没有被 Python 处理(它被设置为 signal.SIG_DFLsignal.SIG_IGN),这个函数什么都不做。

int PySignal_SetWakeupFd(int fd)

此实用程序函数指定一个文件描述符,每当接收到信号时,信号编号将作为单个字节写入该文件描述符。 fd 必须是非阻塞的。 它返回以前的此类文件描述符。

-1 禁用该功能; 这是初始状态。 这相当于 Python 中的 signal.set_wakeup_fd(),但没有任何错误检查。 fd 应该是一个有效的文件描述符。 该函数只能从主线程调用。

3.5 版更改: 在 Windows 上,该函数现在也支持套接字句柄。


异常类

PyObject *PyErr_NewException(const char *name, PyObject *base, PyObject *dict)

此实用程序函数创建并返回一个新的异常类。 name 参数必须是新异常的名称,即 module.classname 形式的 C 字符串。 basedict 参数通常是 NULL。 这将创建一个派生自 Exception 的类对象(在 C 中可作为 PyExc_Exception 访问)。

新类的 __module__ 属性设置为 name 参数的第一部分(直到最后一个点),类名设置为最后一部分(最后一个点之后)点)。 base 参数可用于指定替代基类; 它可以只是一个类,也可以是一组类。 dict 参数可用于指定类变量和方法的字典。

PyObject *PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict)

PyErr_NewException() 相同,除了新的异常类可以很容易地被赋予一个文档字符串:如果 doc 是非 NULL,它将被用作文档字符串对于异常类。

3.2 版中的新功能。


异常对象

PyObject *PyException_GetTraceback(PyObject *ex)
返回与异常关联的回溯作为新引用,可通过 __traceback__ 从 Python 访问。 如果没有关联回溯,则返回 NULL
int PyException_SetTraceback(PyObject *ex, PyObject *tb)
将与异常关联的回溯设置为 tb。 使用 Py_None 清除它。
PyObject *PyException_GetContext(PyObject *ex)
返回与异常关联的上下文(在其处理 ex 期间引发的另一个异常实例)作为新引用,可通过 __context__ 从 Python 访问。 如果没有关联的上下文,则返回 NULL
void PyException_SetContext(PyObject *ex, PyObject *ctx)
将与异常关联的上下文设置为 ctx。 使用 NULL 清除它。 没有类型检查来确保 ctx 是一个异常实例。 这窃取了对 ctx 的引用。
PyObject *PyException_GetCause(PyObject *ex)
返回与异常关联的原因(异常实例或 None,由 raise ... from ... 设置)作为新引用,可通过 __cause__ 从 Python 访问。
void PyException_SetCause(PyObject *ex, PyObject *cause)

将与异常相关的原因设置为 cause。 使用 NULL 清除它。 没有类型检查来确保 cause 是异常实例或 None。 这窃取了对 cause 的引用。

__suppress_context__ 被此功能隐式设置为 True


Unicode 异常对象

以下函数用于从 C 创建和修改 Unicode 异常。

PyObject *PyUnicodeDecodeError_Create(const char *encoding, const char *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason)
创建一个 UnicodeDecodeError 对象,其属性为 encodingobjectlengthstart、end[ X140X] 和 原因encodingreason 是 UTF-8 编码的字符串。
PyObject *PyUnicodeEncodeError_Create(const char *encoding, const Py_UNICODE *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason)

创建一个 UnicodeEncodeError 对象,其属性为 encodingobjectlengthstart、end[ X140X] 和 原因encodingreason 是 UTF-8 编码的字符串。

自 3.3 版起已弃用:3.11

Py_UNICODE 自 Python 3.3 起已弃用。 请迁移到PyObject_CallFunction(PyExc_UnicodeEncodeError, "sOnns", ...)

PyObject *PyUnicodeTranslateError_Create(const Py_UNICODE *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason)

创建一个 UnicodeTranslateError 对象,其属性为 objectlengthstartend 和 reason[ X144X]。 reason 是一个 UTF-8 编码的字符串。

自 3.3 版起已弃用:3.11

Py_UNICODE 自 Python 3.3 起已弃用。 请迁移到PyObject_CallFunction(PyExc_UnicodeTranslateError, "Onns", ...)

PyObject *PyUnicodeDecodeError_GetEncoding(PyObject *exc)


PyObject *PyUnicodeEncodeError_GetEncoding(PyObject *exc)

返回给定异常对象的 encoding 属性。
PyObject *PyUnicodeDecodeError_GetObject(PyObject *exc)


PyObject *PyUnicodeEncodeError_GetObject(PyObject *exc)

PyObject *PyUnicodeTranslateError_GetObject(PyObject *exc)

返回给定异常对象的 object 属性。
int PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start)


int PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start)

int PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start)

获取给定异常对象的 start 属性并将其放入 *startstart 不能是 NULL。 成功返回 0,失败返回 -1
int PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start)


int PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start)

int PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start)

将给定异常对象的 start 属性设置为 start。 成功返回 0,失败返回 -1
int PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end)


int PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end)

int PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *end)

获取给定异常对象的 end 属性并将其放入 *endend 不能是 NULL。 成功返回 0,失败返回 -1
int PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end)


int PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end)

int PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end)

将给定异常对象的 end 属性设置为 end。 成功返回 0,失败返回 -1
PyObject *PyUnicodeDecodeError_GetReason(PyObject *exc)


PyObject *PyUnicodeEncodeError_GetReason(PyObject *exc)

PyObject *PyUnicodeTranslateError_GetReason(PyObject *exc)

返回给定异常对象的 reason 属性。
int PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason)


int PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason)

int PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason)

将给定异常对象的 reason 属性设置为 reason。 成功返回 0,失败返回 -1


递归控制

这两个函数提供了一种在核心和扩展模块中在 C 级别执行安全递归调用的方法。 如果递归代码不一定调用 Python 代码(自动跟踪其递归深度),则需要它们。 tp_call 实现也不需要它们,因为 调用协议 负责递归处理。

int Py_EnterRecursiveCall(const char *where)

标记将要执行递归 C 级调用的点。

如果定义了 USE_STACKCHECK,则此函数使用 PyOS_CheckStack() 检查操作系统堆栈是否溢出。 在这种情况下,它设置 MemoryError 并返回一个非零值。

然后该函数检查是否达到递归限制。 如果是这种情况,则设置 RecursionError 并返回非零值。 否则,返回零。

where 应该是 UTF-8 编码的字符串,例如 " in instance check" 连接到由递归深度限制引起的 RecursionError 消息。

3.9 版本变更: 此功能现在也可以在有限的 API 中使用。

void Py_LeaveRecursiveCall(void)

结束 Py_EnterRecursiveCall()。 对于 Py_EnterRecursiveCall() 的每次 successful 调用,必须调用一次。

3.9 版本变更: 此功能现在也可以在有限的 API 中使用。

为容器类型正确实现 tp_repr 需要特殊的递归处理。 tp_repr除了保护栈,还需要跟踪对象,防止循环。 以下两个函数有助于实现此功能。 实际上,这些是等效于 reprlib.recursive_repr() 的 C。

int Py_ReprEnter(PyObject *object)

tp_repr 实现的开头调用以检测循环。

如果对象已经被处理,函数返回一个正整数。 在这种情况下,tp_repr 实现应该返回一个字符串对象,指示一个循环。 例如,dict 对象返回 {...}list 对象返回 [...]

如果达到递归限制,该函数将返回一个负整数。 在这种情况下,tp_repr 实现通常应该返回 NULL

否则,函数返回零,tp_repr 实现可以正常继续。

void Py_ReprLeave(PyObject *object)
结束 Py_ReprEnter()。 每次调用返回零的 Py_ReprEnter() 时必须调用一次。


标准例外

所有标准 Python 异常都可用作全局变量,其名称为 PyExc_ 后跟 Python 异常名称。 它们的类型为 PyObject*; 它们都是类对象。 为了完整起见,以下是所有变量:

姓名 蟒蛇名称 笔记
PyExc_BaseException BaseException (1)
PyExc_Exception Exception (1)
PyExc_ArithmeticError ArithmeticError (1)
PyExc_AssertionError AssertionError
PyExc_AttributeError AttributeError
PyExc_BlockingIOError BlockingIOError
PyExc_BrokenPipeError BrokenPipeError
PyExc_BufferError BufferError
PyExc_ChildProcessError ChildProcessError
PyExc_ConnectionAbortedError ConnectionAbortedError
PyExc_ConnectionError ConnectionError
PyExc_ConnectionRefusedError ConnectionRefusedError
PyExc_ConnectionResetError ConnectionResetError
PyExc_EOFError EOFError
PyExc_FileExistsError FileExistsError
PyExc_FileNotFoundError FileNotFoundError
PyExc_FloatingPointError FloatingPointError
PyExc_GeneratorExit GeneratorExit
PyExc_ImportError ImportError
PyExc_IndentationError IndentationError
PyExc_IndexError IndexError
PyExc_InterruptedError InterruptedError
PyExc_IsADirectoryError IsADirectoryError
PyExc_KeyError KeyError
PyExc_KeyboardInterrupt KeyboardInterrupt
PyExc_LookupError LookupError (1)
PyExc_MemoryError MemoryError
PyExc_ModuleNotFoundError ModuleNotFoundError
PyExc_NameError NameError
PyExc_NotADirectoryError NotADirectoryError
PyExc_NotImplementedError NotImplementedError
PyExc_OSError OSError (1)
PyExc_OverflowError OverflowError
PyExc_PermissionError PermissionError
PyExc_ProcessLookupError ProcessLookupError
PyExc_RecursionError RecursionError
PyExc_ReferenceError ReferenceError (2)
PyExc_RuntimeError RuntimeError
PyExc_StopAsyncIteration StopAsyncIteration
PyExc_StopIteration StopIteration
PyExc_SyntaxError SyntaxError
PyExc_SystemError SystemError
PyExc_SystemExit SystemExit
PyExc_TabError TabError
PyExc_TimeoutError TimeoutError
PyExc_TypeError TypeError
PyExc_UnboundLocalError UnboundLocalError
PyExc_UnicodeDecodeError UnicodeDecodeError
PyExc_UnicodeEncodeError UnicodeEncodeError
PyExc_UnicodeError UnicodeError
PyExc_UnicodeTranslateError UnicodeTranslateError
PyExc_ValueError ValueError
PyExc_ZeroDivisionError ZeroDivisionError

3.3 新功能:PyExc_BlockingIOErrorPyExc_BrokenPipeErrorPyExc_ChildProcessErrorPyExc_ConnectionErrorPyExc_ConnectionAbortedError、[ X88X]、PyExc_ConnectionResetErrorPyExc_FileExistsErrorPyExc_FileNotFoundErrorPyExc_InterruptedErrorPyExc_IsADirectoryErrorPyExc_NotADirectoryError、[X17X] ]、PyExc_ProcessLookupErrorPyExc_TimeoutError 是在 PEP 3151 之后引入的。


3.5 版新增:PyExc_StopAsyncIterationPyExc_RecursionError


3.6 版新增:PyExc_ModuleNotFoundError


这些是 PyExc_OSError 的兼容性别名:

姓名 笔记
PyExc_EnvironmentError
PyExc_IOError
PyExc_WindowsError (3)

3.3 版更改: 这些别名曾经是单独的异常类型。


笔记:

  1. 这是其他标准异常的基类。
  2. 仅在 Windows 上定义; 通过测试预处理器宏 MS_WINDOWS 的定义来保护使用它的代码。


标准警告类别

所有标准 Python 警告类别都可用作全局变量,其名称为 PyExc_ 后跟 Python 异常名称。 它们的类型为 PyObject*; 它们都是类对象。 为了完整起见,以下是所有变量:

姓名 蟒蛇名称 笔记
PyExc_Warning Warning (1)
PyExc_BytesWarning BytesWarning
PyExc_DeprecationWarning DeprecationWarning
PyExc_FutureWarning FutureWarning
PyExc_ImportWarning ImportWarning
PyExc_PendingDeprecationWarning PendingDeprecationWarning
PyExc_ResourceWarning ResourceWarning
PyExc_RuntimeWarning RuntimeWarning
PyExc_SyntaxWarning SyntaxWarning
PyExc_UnicodeWarning UnicodeWarning
PyExc_UserWarning UserWarning

3.2 版新增:PyExc_ResourceWarning


笔记:

  1. 这是其他标准警告类别的基类。