[Python-ideas] Use `isinstance` check during exception handling
sjoerdjob at sjec.nl
sjoerdjob at sjec.nl
Thu Nov 5 01:00:12 EST 2015
> On 11/4/2015 5:02 PM, sjoerdjob at sjec.nl wrote:
>> TL;DR: Change exception checking logic from
>> err.__class__ in exc.__mro__
>
> This is backwards. err.__class__ must be a (true) subclass, not a
> superclass, of exc, where err = exception instance, exc = exception class.
Ah, a minor glitch when writing the e-mail. My apologies. It should be
exc in err.__class__.__mro__
> There are two checks in the exception process. First, for 'raise err',
> is that err is a instance of StopIteration, which is to say,
> err.__class__ is a subclass of StopIteration. To avoid the fakery of
> __instancecheck__ and __subclasscheck__, I presume this is implemented
> as something like one of
> StopIteration in err.__class__.__mro__
> StopIteration in type(err).__mro__
> (There was a recent pydev discussion about when and why these may
> diverge.)
I can't actually find the logic which handles the `StopIteration`,
unless you are talking specifically about the exception handling in
for-loops and everything else that relates to iterables. (The code I'm
looking at is Python/errors.c:PyErr_GivenExceptionMatches).
> The second, for 'except exc', is that exc is a superclass (other than
> object) of type(err). I presume this is implemented as something like
> exc in type(err)[:-1] # exclude object class
> This assume that err has already passed the first check above.
>From what I can find (again: errors.c), the current logic is:
(note: `err` is what is raised, `exc` is what's matched against)
* if `exc` is a tuple, recurse over the elements of the tuple.
* if the `err` is an instance, replace it with its class
* if both `err` and `exc` are subclasses of exception:
check PyType_IsSubtype(err, exc)
which basically is the same as (see Objects/typeobject.c)
exc in err.__mro__
note: not err.__mro__[:-1].
> The `try` doc says "An object is compatible with an exception if it is
> the class or a base class of the exception object". This text fails to
> exclude the object class as a compatible object. CPython code rejects
> 'except object:' with "TypeError: catching classes that do not inherit
> from BaseException is not allowed"
>
>> to
>> isinstance(err, exc)
>> Because it is more powerful,
>
> ?? This predicate is True more often than the current one because it a)
> does not exclude exc = object
My idea was basically to still demand that both `err` and `exc` must
sub-class `BaseException`, but that only the check for
`PyType_IsSubtype` would be replaced with `PyObject_IsInstance`.
> >>> isinstance(Exception(), object)
> True
>
> and b) accesses exc.__instancecheck__ (which is part of your point).
> This makes it a weaker predicate.
Yes, the predicate is weaker. And that gives us more power.
> I don't have strong opinions at the moment about the proposal itself,
> but semantic changes in core python syntax need a PEP (once you think
> there is *some* support).
It's not a syntax-change, but a semantics-change. Still I would not be
surprised if it indeed does need a PEP, but there will only be a point
in doing that when there is *some* support. Before writing that PEP, I
was checking here to see if I could find some support, or if it the pros
don't outweigh the cons for the 'masses'.
> --
> Terry Jan Reedy
Regards,
Sjoerd Job Postmus
More information about the Python-ideas
mailing list