This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author belopolsky
Recipients alexandre.vassalotti, belopolsky, eric.araujo, grubert, jackdied, pitrou, rhettinger, schmir, zzzeek
Date 2010-07-17.23:43:14
SpamBayes Score 2.0833657e-08
Marked as misclassified No
Message-id <1279410197.28.0.927282672898.issue9269@psf.upfronthosting.co.za>
In-reply-to
Content
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
SUCCESS
    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.
History
Date User Action Args
2010-07-17 23:43:17belopolskysetrecipients: + belopolsky, rhettinger, grubert, pitrou, jackdied, alexandre.vassalotti, schmir, eric.araujo, zzzeek
2010-07-17 23:43:17belopolskysetmessageid: <1279410197.28.0.927282672898.issue9269@psf.upfronthosting.co.za>
2010-07-17 23:43:15belopolskylinkissue9269 messages
2010-07-17 23:43:14belopolskycreate