Issue 1742889: Pickling of exceptions broken (original) (raw)
Exceptions with required initialization arguments can't be unpickled:
class E(Exception): ... def init(self, x): ... self.x = x ... import pickle e = E(1) p = pickle.dumps(e, 1) pickle.loads(p) Traceback (most recent call last): File "", line 1, in File "/usr/local/python/2.5.1/lib/python2.5/pickle.py", line 1374, in loads return Unpickler(file).load() File "/usr/local/python/2.5.1/lib/python2.5/pickle.py", line 858, in load dispatchkey File "/usr/local/python/2.5.1/lib/python2.5/pickle.py", line 1133, in load_reduce value = func(*args) TypeError: init() takes exactly 2 arguments (1 given)
This is because reduce defined in exceptions.c returns the type and the args variable, which an exception subclass might not populate.
Also, the reduce implementation doesn't properly serialize the message attribute.
I assume that the need for a custom reduce is due to the micro-optimization to store arge and message in C slots. Is this really necessary?
I'm not aware of any such contract. Can you point to anything in writing?
See for example:
file:///home/jim/Documentation/Python-Docs-2.4.1/tut/node10.html#SECTION0010500000000000000000
which teaches people to create custom exceptions that:
don't set args ro message and
won't be unpicklable in Python 2.5.
Also, as I mentioned, the reduce implementation doesn't preserve the message, so even if that was the contract, the contract is broken.