假设我有一个带有抽象基类的异常类,如下所示:
class MyExceptions(BaseExeption, metaclass=abc.ABCMeta):
pass
class ProperSubclass(MyExceptions):
pass
MyExceptions.register(ValueError)看来我可以用MyExceptions来捕获MyExceptions,但不能用ValueError捕获
try:
raise ProperSubclass()
except MyExceptions:
print('As expected, control comes here...')
except:
print('...and not here.')
try:
raise ValueError()
except MyExceptions:
print('Control does not come here...')
except ValueError:
print('...but unexpectedly comes here.')因此,我的问题是,我应该能够捕捉到他们抽象基类的内置异常吗?如果是这样的话,是怎么做的?如果没有,规则是什么?
我想问这个问题的另一种方法是:是否除了子句正确地使用isinstance()/issubclass()进行匹配,如果不是(看起来是这样的)它们使用什么?也许在C实现中有一些模糊的快捷方式。
发布于 2014-05-27 14:14:05
文档说:
如果对象是异常对象的类或基类,或者包含与异常兼容的项的元组,则该对象与异常兼容。
不幸的是,这并没有说明是否应该考虑虚拟基类,这与用于例如等子类的语言不同
如果类是classinfo的子类(直接、间接或虚拟),则返回true。..。
覆盖实例和子类检查的语言也没有多大帮助:
以下方法用于覆盖
isinstance()和issubclass()内置函数的默认行为。..。
实际上,正如您所怀疑的,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);作为参考,is子类的CPython实现IsSubclass在返回到PyType_IsSubtype之前调用__subclasscheck__。
因此,这种行为有一个很好的理由;异常处理需要是非递归的,因此调用Python代码是不安全的。注意,Python2.7版本接受溢出的风险,并调用PyObject_IsSubclass。Python3中有一个放宽这项限制的建议,但是虽然已经编写了一个修补程序,但它还没有被接受。否则,文档最好澄清except检查是非虚拟的。
https://stackoverflow.com/questions/23890645
复制相似问题