Skip to content

Pickling fails for immutable objects that occur in recursive structures #458

@anivegesana

Description

@anivegesana

Minimal failure case:

def f():
  d = {}
  def g():
    return d
  d['g'] = g
  return g

import dill
dill.dumps(f())

g.__closure__ contains g, but not directly. Currently, save_cell only breaks cycles that directly contain the function, not collections or objects that contain the function.

CloudPickle's solution of breaking the cycles within functions as opposed to within cells (like dill does) may be undesirable in some situations:

import cloudpickle

class C:
  def __init__(self, fx):
    self.fx = fx
    print(self.fx.d)
  def __reduce__(self):
    return (C, (self.fx,))

def f():
  t = ((lambda: t),)
  t[0].d = 0
  t[0].c = C(t[0])
  return t

pkl = cloudpickle.dumps(f())
cloudpickle.loads(pkl)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
AttributeError: 'function' object has no attribute 'd'

Therefore, a more dynamic cycle breaking mechanism would be preferred, but tradeoffs of each method should be deliberated.

Another example:

uqfoundation/mystic@f6f71f5

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions