Isue #5084: unpickling now interns the attribute names of pickled objects,
saving memory and avoiding growth in size of subsequent pickles. Proposal and original patch by Jake McGuire.
This commit is contained in:
parent
2b42c29a50
commit
7430989cda
|
@ -1221,7 +1221,15 @@ class Unpickler:
|
|||
state, slotstate = state
|
||||
if state:
|
||||
try:
|
||||
inst.__dict__.update(state)
|
||||
d = inst.__dict__
|
||||
try:
|
||||
for k, v in state.iteritems():
|
||||
d[intern(k)] = v
|
||||
# keys in state don't have to be strings
|
||||
# don't blow up, but don't go out of our way
|
||||
except TypeError:
|
||||
d.update(state)
|
||||
|
||||
except RuntimeError:
|
||||
# XXX In restricted execution, the instance's __dict__
|
||||
# is not accessible. Use the old way of unpickling
|
||||
|
|
|
@ -938,6 +938,20 @@ class AbstractPickleTests(unittest.TestCase):
|
|||
"Failed protocol %d: %r != %r"
|
||||
% (proto, obj, loaded))
|
||||
|
||||
def test_attribute_name_interning(self):
|
||||
# Test that attribute names of pickled objects are interned when
|
||||
# unpickling.
|
||||
for proto in protocols:
|
||||
x = C()
|
||||
x.foo = 42
|
||||
x.bar = "hello"
|
||||
s = self.dumps(x, proto)
|
||||
y = self.loads(s)
|
||||
x_keys = sorted(x.__dict__)
|
||||
y_keys = sorted(y.__dict__)
|
||||
for x_key, y_key in zip(x_keys, y_keys):
|
||||
self.assertIs(x_key, y_key)
|
||||
|
||||
|
||||
# Test classes for reduce_ex
|
||||
|
||||
|
|
|
@ -261,6 +261,10 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #5084: unpickling now interns the attribute names of pickled objects,
|
||||
saving memory and avoiding growth in size of subsequent pickles. Proposal
|
||||
and original patch by Jake McGuire.
|
||||
|
||||
- Issue #3002: ``shutil.copyfile()`` and ``shutil.copytree()`` now raise an
|
||||
error when a named pipe is encountered, rather than blocking infinitely.
|
||||
|
||||
|
|
|
@ -4473,8 +4473,16 @@ load_build(Unpicklerobject *self)
|
|||
|
||||
i = 0;
|
||||
while (PyDict_Next(state, &i, &d_key, &d_value)) {
|
||||
if (PyObject_SetItem(dict, d_key, d_value) < 0)
|
||||
/* normally the keys for instance attributes are
|
||||
interned. we should try to do that here. */
|
||||
Py_INCREF(d_key);
|
||||
if (PyString_CheckExact(d_key))
|
||||
PyString_InternInPlace(&d_key);
|
||||
if (PyObject_SetItem(dict, d_key, d_value) < 0) {
|
||||
Py_DECREF(d_key);
|
||||
goto finally;
|
||||
}
|
||||
Py_DECREF(d_key);
|
||||
}
|
||||
Py_DECREF(dict);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue