[Python-3000] removing exception .args

Andrew Dalke dalke at dalkescientific.com
Sat Jul 21 23:16:35 CEST 2007


The main statement I have is, excepting backwards compatibility,
nothing would care if .args was removed in 3.0, and those which
currently used .args were changed to use attributes instead.

Please show/advise me otherwise.

> Andrew Dalke wrote:
>> so I think the base exception class should look like
>> class Exception(object):
>>    msg = None
>>    def __init__(self, msg):
>>      self.msg = msg
>>    def __str__(self):
>>      if self.msg is not None:
>>        return "%s()" % (self.__class__.__name__,)
>>      else:
>>        return "%s(%r)" % (self.__class__.__name__, self.msg)

On Jul 21, 2007, at 8:02 PM, Nick Coghlan wrote:
> Went there, didn't like it, left again. See PEP 352,

Sure, fine.  The "pragmatic" thing I care about is allowing a
single argument to be passed in the base exception class, which
in turn is used in the __str__ / __repr__.  If it's called
"message" or "msg" or stored in .args as a single element
tuple, I don't care.

For example, this would also be fine to me.

class Exception(object):
    __obj = object()
    def __init__(self, msg):
      self.__obj = msg
    def __repr__(self):
      if self.__obj is Exception.__obj:
        return "%s()" % (self.__class__.__name__,)
      else:
        return "%s(%r)" % (self.__class__.__name__, self.__obj)


> especially the section on the late (unlamented) BaseException.message.

I'm more hoping for this part of the "retracted ideas" section:

     ... and consider a more long-term transition strategy in
     Python 3.0 to remove multiple-argument support in
     BaseException in preference of accepting only a single argument.

That section also says that removing 'args' during the transition
is hard.  I can believe it.  But Python 3 can be non-backwards
compatible.

> As of Python 2.5, you can rely on the attribute being present,
> as it is provided automatically by BaseException:

Yes, I know that.

Is it useful?  Is having an autogenerated, empty .args useful?

Why?  What code would break? (excepting backwards compatibility
for code that expects to extra information via position instead
of attribut)

As far as I can tell, it's not useful.  And that's why it
should be deleted.

If it were useful, then explain why 'filename' isn't in the
args list for IOError, as in

 >>> import os
 >>> err = IOError(2, os.strerror(2), "/path/to/nowhere")
 >>> err.args
(2, 'No such file or directory')
 >>> repr(err)
"IOError(2, 'No such file or directory')"
 >>> err.errno
2
 >>> err.strerror
'No such file or directory'
 >>> err.filename
'/path/to/nowhere'
 >>>


Answer: it's a bug.  But it's a bug that no one really
cares about.  Its lack affects no one.  And removing 'args'
would affect .. no one.  Excepting code which currently
expects to get fields [0], [1], ... when the original
exception should have defined attributes instead.

> If you want to avoid requiring that subclasses call your
> __init__ method, you can actually do that by putting any
> essential initialisation into the __new__ method instead.

That wasn't my point.  My point is that many non-trivial
exception classes don't currently call the base class
__init__ nor set the .vars attribute.  That one class I
showed was an example of defensive programming - knowing
that there's a decent chance that derived classes won't
call the __init__.

There should be no reason to be this defensive.  Most
other classes are not.  That getopt example was a second-order
effect and should not be a driving case for any future
direction.

The real problem isn't that .args wasn't initialized.
The real problem is that .args shouldn't need to exist.

(In personal email I did a followup on why I think __new__
should not be used for this case, or for the more generally
advocated case of "setting up class invariants in the base
class."  I felt that that was a distracting tangent.)


				Andrew
				dalke at dalkescientific.com




More information about the Python-3000 mailing list