[Python-ideas] Arguments to exceptions
Stephen J. Turnbull
turnbull.stephen.fw at u.tsukuba.ac.jp
Mon Jul 17 11:20:55 EDT 2017
First, I would like to make it clear that I am not claiming that
the current design of standard Exceptions cannot be improved, nor do I
necessarily have a problem with doing it at the BaseException level.
My argument has always been directed to the issue of "does changing
BaseException actually save work in design and implementation of the
interpreter, of standard derived Exceptions, and of new user
Exceptions?" I don't think it does.
But Ken and you have taken opposition to Ken's proposal to indicate
that we don't see a problem with the current implementation of the
standard Exception hierarchy. That's not true. We do understand the
problems. We differ on importance: Steven d'A seems to deprecate the
NameError in "data-sets-formatted-as-Python-containers" problem as
rare and only encountered by a few users. I think that's a big enough
class of use cases (I do it myself, though I've never encountered
Ken's use case) to worry about, though I wouldn't be willing to do the
work myself on the evidence so far presented. But we do understand.
What you and Ken haven't done yet is to show
1. the implementation of an improvement is simple and generic, and
2. enough so to justify what seems to be an improvement restricted to
an uncommon set of use cases.
Nick has helped to convince me that (1) can be addressed, though he
warned that it's not all that easy (especially if you're a DRY
fanatic). The question then is the balance between (1) and (2).
Jeff Walker writes:
> The first problem is that there is no direct access to the
> components that make up the error in some of the standard Python
That's not a problem in BaseException, though. BaseException allows
access to arbitrary Python objects, if, and only if, the developer
puts them in the exception.
> Why wasn't that done?
I don't know, but it's not prevented by BaseException.
> That leads us to the second problem: the base exception does not
> handle arguments gracefully unless you only pass an error message
> all by itself.
I think it would have been a mistake to try to do something graceful.
The point is that looking at the design, I would suppose that
BaseException had only one job: conveying whatever information the
programmer chose to put in it faithfully to an exception handler. It
does that, even if you hand it something really wierd, and in several
This is called "humility in design when you have no idea what you're
designing for". The Zen expresses it "But sometimes never is better
than *right* now." It's easy to design a better BaseException for a
handful of cases. It's not at all clear that such a BaseException
would work well for more than a double handful. If it doesn't, it
would tend to cause the same problem for exceptions that don't fit it
very well but the programmer doesn't think are important enough to
deserve a well-defined derived Exception. Since it would necessarily
be more complex than the current BaseException, it might have even
uglier failure modes.
> >>> try:
> >>> name = 'foo'
> >>> raise NameError(name, '%s: name is not defined.' % name)
l > >>> except NameError as e:
> >>> print(str(e))
> ('foo', 'foo: name is not defined.')
> In this case, printing the exception cast to a string does not
> result in a reasonable error message.
Sure, but that's because the error message was poorly chosen. I would
raise NameError(name, 'error: undefined name')
which would stringify as
('foo', 'error: undefined name')
(and there are probably even better ways to phrase that). But in the
case of NameError, I don't understand why a string is used at all. I
really don't see a problem with the interpreter printing
and a traceback indicating where "foo" was encountered, and having
programmatic handlers do something appropriate with e.args. It's
not obvious to me that the same is not true of most of the "stupid
string formatting" Exceptions that have been given as examples.
> So the basic point is that the lack of reasonable behavior for
I hate to tell you this, but str doesn't guarantee anything like
reasonable behavior for error handling. Even repr doesn't guarantee
you can identify an object passed to it, nor reproduce it.
I have to assume that the developers who designed these Exceptions
believed that in the vast majority of cases the mere fact that an
instance of particular Exception was raised is enough to identify the
offending object. Perhaps they were mistaken. But if they were, the
places in the interpreter where they are raised and handled all must
be be checked to see if they need to be changed, whether we change
BaseException or the individual derived Exceptions. And if we change
BaseException, I expect it will be very desirable to change individual
derived Exceptions as well (to give them intelligible error message
Also, it's not obvious to me that default templates are such a useful
idea. I almost always use unique messages when "printf debugging",
out of habit developed in other languages. That means I rarely have
to look at tracebacks for simple errors. If better templates make it
easier for people to not use context-specific messages, when they are
warranted that's not a win, I think.
> But in fact [use of keyword arguments to set "advanced" formatting]
> is not really the point of the proposal, it is just a minor design
I don't think it's so minor. The keyword argument approach was
apparently chosen to avoid breaking backward compatibility in
BaseException. Compatibility break is not an option here, IMO. I
think it's also an important part of Ken's proposal that this be an
"easy" tweak that makes it easier to write better derived Exceptions
and better exception handling in many cases.
> But sometimes you just want something quick that you can use that
> does not require you to define your own exception. And sometimes,
> even though people should define custom exceptions, they don't. For
> example, NameError, KeyError, IndexError, ...
I don't see how that is an argument for the proposed change to
More information about the Python-ideas