Raising objects

Steven Taschuk staschuk at telusplanet.net
Wed Apr 30 22:36:40 EDT 2003


Quoth Alex Martelli:
> Steven Taschuk wrote:
  [...]
> > This function does report that strings and lists are new-style.
> > Aren't they?
> 
> If by "new-style" you mean "anything EXCEPT classic classes" then
> yes, of course -- strings, lists, numbers, etc, aren't classic
> classes.  But then it's simpler to check for types.ClassType, no?

Ah yes, the type/class distinction.  I frequently forget that.

So what then is the distinction between new-style classes and
types?  (Other than that types are not quite reliably subclassable
yet, or so I hear.)

  [...]
> Moreover, if what you raise is always derived by Exception, the
> Exception base class can ensure all sort of nice error-reporting

A good point.

But usually in Python we do not care whether an object inherits
from a specific subclass; we only care whether it has the
attributes we need it to have.  Why should the error-reporting
facilities of Exception be any different?

In other words, why should we stop a programmer who *doesn't* want
those error-reporting facilities from raising some other object?
Isn't trusting the programmer pythonic?

> > So, suppose that strings were special-cased for backwards
> > compatibility:
  [...]
> > Is there a problem with this scheme?
> 
> The horrid complexity and specialcasing is problematic enough
> for me.  Allowing such generality in what is raised buys you
> nothing pragmatically useful AND you pay a price in complexity.
> No thanks!!!

I agree the pragmatic gain is negligible.  (Except for a
simplification of the rules for exceptions; I'll explain this
below.)

Forget the special-casing of strings; I overlooked that we need
the identity test (not an equality test, as I erroneously wrote)
so that
    raise ValueError # the class, not an instance of it!
will be caught by an up-stack
    except ValueError:
clause.  (My excuse for forgetting this is that I always raise
instances.)

I'd like to get rid of this; it seems conceptually wrong to me
that a class and its instances are interchangeable in this
respect.  The identity test which makes it work made sense back
when exceptions were strings (as you explained so cogently), but
imho it's now a (minor) wart for backwards compatibility.

So, what I'd like to see eventually is this:

    Raise anything you like.

    An except clause catches an exception e if and only if it
    names a type of which e is an instance.

This seems simpler than what you would want to see eventually:

    Raise any subclass of (New)Exception, or an instance of such
    a subclass.

    An except clause catches an exception if and only if it
    names either a type of which e is an instance, or an object
    which is identical to e.

(Hopefully I've correctly understood what you're saying.)  Either
of these is, of course, simpler than the present rules.

The only disadvantage of my ideal scenario that I can see is that
it introduces a new kind of "forgot the parentheses" bug;
    raise ValueError
would raise an exception which would go right past
    except ValueError:
and only be caught by the very unlikely
    except type:
or a bare except.

To get from the present rules to my ideal scenario, the identity
test has to be removed, and while we're at it, the syntax
    raise foo, bar
should go too.  (Again, it made sense back when exceptions were
strings.)  And perhaps sys.exc_* would have to be revised as well.
The path seems straightforward:

    Step 0.  Revise the Tutorial to advocate "raise ValueError(...)"
    instead of "raise ValueError, ...".  Mention the latter only as
    an old way of doing things.

    Step 1.  Issue warnings when an exception is caught by the
    identity test, and when the "raise foo, bar" syntax is used.
    (These warnings could be phased in via __future__ if desired.)

    Step 2.  Remove the identity test; catch only by the isinstance
    test.  Remove the "raise foo, bar" syntax.  Revise sys.exc_*
    if appropriate.

    Step 3.  Make Exception a new-style class.

    Step 4.  Allow anything to be raised.

(I haven't thought about the e in
    except ValueError, e:
yet.)

Hm... maybe I should write a PEP.

-- 
Steven Taschuk                                7\ 7'Z {&~         .
staschuk at telusplanet.net                        Y r          --/hG-
                                            (__/ )_             1^1`





More information about the Python-list mailing list