[issue9269] Cannot pickle self-referencing sets
report at bugs.python.org
Sun Jul 18 01:43:17 CEST 2010
Alexander Belopolsky <belopolsky at users.sourceforge.net> added the comment:
Upon further investigation, I am no longer convinced that "reduce cycles" are necessarily fatal to pickling. I am attaching a script testcycle.py that allows creating cycles using various containers. It takes the name of container class as an argument and prints SUCCESS/FAILURE followed by annotated pickle disassembly. It turns out that self-referential tuples are pickled successfully even though being immutable, they must receive their state through arguments:
$ ./python.exe testcycle.py tuple
0: \x80 PROTO 3 Protocol version indicator.
2: c GLOBAL '__main__ C' Push a global object (module.attr) on the stack.
14: ) EMPTY_TUPLE Push an empty tuple.
15: \x81 NEWOBJ Build an object instance.
16: q BINPUT 1 Store the stack top into the memo. The stack is not popped.
18: } EMPTY_DICT Push an empty dict.
19: X BINUNICODE 'foo' Push a Python Unicode string object.
27: h BINGET 1 Read an object from the memo and push it on the stack.
29: \x85 TUPLE1 Build a one-tuple out of the topmost item on the stack.
30: q BINPUT 4 Store the stack top into the memo. The stack is not popped.
32: s SETITEM Add a key+value pair to an existing dict.
33: b BUILD Finish building an object, via __setstate__ or dict update.
34: 0 POP Discard the top stack item, shrinking the stack by one item.
35: h BINGET 4 Read an object from the memo and push it on the stack.
37: . STOP Stop the unpickling machine.
highest protocol among opcodes = 2
There is a comment in save_tuple() that explains how it works:
# Subtle. d was not in memo when we entered save_tuple(), so
# the process of saving the tuple's elements must have saved
# the tuple itself: the tuple is recursive. The proper action
# now is to throw away everything we put on the stack, and
# simply GET the tuple (it's already constructed). This check
# could have been done in the "for element" loop instead, but
# recursive tuples are a rare thing.
I wonder if the same trick could be used in save_reduce() to resolve #1062277 by pickling "reduce cycles" correctly instead of bailing out when they are encountered.
priority: low -> normal
Python tracker <report at bugs.python.org>
More information about the Python-bugs-list