[Python-Dev] Re: PEP-317

Steven Taschuk staschuk@telusplanet.net
Tue, 10 Jun 2003 00:11:18 -0600


Quoth Greg Ewing:
  [...]
> I know that's the way it *is*, but I can't see any reason why the
> interpreter couldn't defer instantiation if it wanted to. It should be
> an optimisation that any part of the implementation is free to make if
> the programmer hasn't explicitly instantiated before raising.

The interpreter certainly could do that, but imho it would be a
Bad Thing.  Forgive my long-windedness, but:

Imho, it's bad enough that
    raise MyError, 'foo'
    raise MyError('foo')
are two ways of saying the same thing; that's merely confusing.
But having the interpreter defer instantiation in the former case
would make them a much worse pair -- two subtly different ways of
saying almost the same thing, where the difference is one you
almost never care about.  I cringe.

To be more concrete, if exception instantiation might be deferred
and might not occur at all, then (off the top of my head):

    1. Logging code in an exception's __init__ might be called,
    might not.

    2. sys._getframe tricks in an exception's __init__ might work,
    might not.  (And exceptions are just the kind of infrastructure-
    level thing where such tricks are most likely to be useful, imho.
    You might, for example, want to grab a copy of all the locals of
    the function which raised the exception, for error reporting.
    Sure you could use the traceback, if you can get ahold of it
    somehow, but everywhere *else* this kind of machinery uses
    sys._getframe, so...)

    3. Implementations of __new__ in which the created object is not
    of the requested class would make the exception type depend on
    whether instantiation was deferred or not, affecting whether and
    when it gets caught.

Perhaps these aren't showstoppers, but I really like it when
optimizations are completely transparent.

Besides, almost all raise statements report errors which prevent
normal processing, and so have no use for such an optimization
anyway.  And even when using exceptions for control flow on
performance- critical paths, you can avoid paying the
instantiation cost in inner loops by other, simpler, means --
e.g., create one instance of your FancyControlFlow exception up
front and raise that one object as needed.

There's also some (surmountable) implementation issues:  Suppose
we enter an except block without instantiating the exception; what
are the values of sys.exc_type etc. then?  Are they possibly
denormalized?  Or do we remove sys.exc_{type, value, traceback}
entirely, and have calling sys.exc_info() cause instantiation?

If explicit instantiation were standard, and the implicit
instantiation syntax were now being proposed with deferred-and-
skipped-if-possible semantics, I might just be -0 YAGNI on it.  In
that scenario, this syntax would be something weird that
programmers would only use if they knew they needed it.  But the
actual circumstance is, to judge by the stdlib, that implicit
instantiation is today the de facto standard way to raise an
exception.  Thus adding such semantics now would give the normal
form weird behaviour to enable an optimization which is useful
only in specialized circumstances -- which puts me firmly in the
-1 AAAGH! camp.

All of the above is intended for pure Python only.  If the
tradeoffs are much different in Pyrex, I'd like to hear more
details.

  [...]
> But something else has occurred to me. If we're going to require
> exception classes to be derived from Exception, then there's no
> ambiguity anyway, [...]

For old-style classes, there's no ambiguity now, either.  But yes,
requiring inheritance from Exception seems to eliminate any
instance/class ambiguities for future new-style exceptions too.
(It also avoids certain other problems; see Alex's persuasive
arguments in c.l.py around the beginning of May, mentioned
elsewhere in this thread.)

PEP 317 isn't primarily concerned with that ambiguity, of course;
more with the loss of clarity in present-day everyday code.

> [...] because you can't have an object which is both a
> subclass of Exception and an instance of a subclass of Exception.  (At
> least not without pulling some sort of bizarre trick, and I don't
> much care what happens to anyone who does that.-)

Couldn't agree more.

-- 
Steven Taschuk                          staschuk@telusplanet.net
"Its force is immeasurable.  Even Computer cannot determine it."
                           -- _Space: 1999_ episode "Black Sun"