Alexander Belopolsky <belopol...@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
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.

----------
priority: low -> normal

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue9269>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to