基于抽象基类捕获异常

2024-09-30 20:31:31 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个异常类,它有一个抽象基类,如下所示:

class MyExceptions(BaseExeption, metaclass=abc.ABCMeta):
    pass

class ProperSubclass(MyExceptions):
    pass

MyExceptions.register(ValueError)

似乎我可以通过MyExceptions捕捉{},但不能{}:

^{pr2}$

所以我的问题是,我应该能够通过抽象基类捕捉内置异常吗?如果是,怎么办?如果没有,规则是什么?在

我想另一种问这个问题的方法是:except子句是否正确地使用isinstance()/issubclass()进行匹配,如果不正确(看起来是这样),它们使用的是什么?也许在C实现中有一些隐藏的快捷方式。在


Tags: 方法register规则pass基类内置classmetaclass
1条回答
网友
1楼 · 发布于 2024-09-30 20:31:31

documentation上写着:

An object is compatible with an exception if it is the class or a base class of the exception object or a tuple containing an item compatible with the exception.

不幸的是,这并没有说明是否应该考虑虚拟基类,这与issubclass的语言不同:

Return true if class is a subclass (direct, indirect or virtual) of classinfo. [...]

重写instance and subclass checks的语言也没有太大帮助:

The following methods are used to override the default behavior of the isinstance() and issubclass() built-in functions. [...]

实际上,正如您所怀疑的那样,CPython实现(对于python3)绕过了子类检查,直接调用PyType_IsSubtype

http://hg.python.org/cpython/file/3.4/Python/errors.c#l167

PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
{
    ...
        /* PyObject_IsSubclass() can recurse and therefore is
           not safe (see test_bad_getattr in test.pickletester). */
        res = PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc);

作为参考,issubclass PyObject_IsSubclass的CPython实现在返回PyType_IsSubtype之前调用__subclasscheck__。在

所以这种行为有一个很好的理由;异常处理需要是非递归的,因此它调用回Python代码是不安全的。注意,Python 2.7 version接受溢出的风险,并且确实调用了PyObject_IsSubclass。python3中有一个proposal to relax this restriction,但是尽管已经编写了一个补丁,但它还没有被接受。否则,文档最好澄清except检查是非虚拟的。在

相关问题 更多 >