[issue1692335] Fix exception pickling: Move initial args assignment to BaseException.__new__

Alexander Belopolsky report at bugs.python.org
Wed Sep 22 20:39:42 CEST 2010


Alexander Belopolsky <belopolsky at users.sourceforge.net> added the comment:

On Wed, Sep 22, 2010 at 9:39 AM, Jason R. Coombs <report at bugs.python.org> wrote:
> .. It appears __getinitargs__ does not work on Python 2.5 or Python 2.7.

Yes,  __getinitargs__  is only used for old style classes.  I was
wrong on that point.

> Exceptions of the following class still raise a TypeError on unpickling:
>
> class D(Exception):
>    """Extension with values, init called with no args."""
>    def __init__(self, foo):
>        self.foo = foo
>        Exception.__init__(self)
>
>    def __getinitargs__(self):
>        return self.foo,
>

The problem with your D class is that it does not provide correct args
attribute which is expected from an exception class:

()

> Using __reduce__ does seem to work. I suspect this is because Exceptions are extension types.
>

There are two ways to fix this class.  Both fix the args issue as well:

1. Pass foo to Exception.__init__  like this: Exception.__init__(self,
foo) in D.__init__.

2. Explicitly initialize self.args: self.args	= foo,

> I think the fundamental problem is that pickling exceptions does not follow the principle of least surprise. In particular:
>
>  - Other built-in objects (dicts, lists, etc) don't require special handling (replace Exception with dict in the above example and it works).

Other built-in objects don't provide an API for retrieving their init arguments.

>  - It's not obvious how to write an Exception subclass that takes additional arguments and make it pickleable.

AFAICT, this is python subclassing 101: if base class __init__ uses
arguments, they should be passed to it by subclass' __init__.

>  - Neither the pickle documentation nor the Exception documentation describe how pickling is implemented in Exceptions.
>

Exception documentation may be improved by adding a section on
subclassing.  Note that the args argument was not even mentioned in
2.7 documentation, so some discussion of its role may be helpful
somewhere.

> Eric has provided some good use cases. Furthermore, it seems counter-intuitive to me to pass a subclass' custom
> arguments to the parent class. Indeed, even the official tutorial defines exception classes that are unpickleable
> (http://docs.python.org/tutorial/errors.html#tut-userexceptions).
>

Well, the tutorial examples should probably be changed.  In these
examples base class __init__ is not called at all which is probably
not a good style.

> If the use case is obvious enough that it shows up in the hello world tutorial, I don't think
> there should be any argument that it's not a common use case.
>

I am not arguing against simplifying Exception subclassing.  I just
don't see an easy solution that would not promote subclasses with
unusable args attribute.  I also disagree with this issue classified
as a bug.  It may be a valid feature request, but not a bug.

In any case, no proponent of this feature has come up with a patch for
3.2 so far and in my view, this would be a prerequisite for moving
this forward.

> At the very least, there should be a section in the pickle documentation or Exception
> documentation describing how one should make a pickleable subclass. ..

I agree, but again someone has to step in to write such section.
Improving documentation may also be the only solution for the 2.x
series.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue1692335>
_______________________________________


More information about the Python-bugs-list mailing list