Python中的pickling weakref

时间:2014-05-14 02:58:58

标签: python pickle weak-references

我仍然是Python的新手,甚至更新的酸洗。我的课程Vertex(ScatterLayout)__getnewargs__()

def __getnewargs__(self):
    return (self.pos, self.size, self.idea.text)

我的理解是,这将导致pickle从__getnewargs__()而不是对象的字典中腌制对象。

使用以下方法(在不同的类MindMapApp(App)中)调用pickle:

def save(self):
    vertices = self.mindmap.get_vertices()
    edges = self.mindmap.get_edges()

    output = open('mindmap.pkl', 'wb')

    #pickle.dump(edges, output, pickle.HIGHEST_PROTOCOL)
    pickle.dump(vertices, output, pickle.HIGHEST_PROTOCOL)

    output.close()

当我调用save()方法时,我收到以下错误:

pickle.PicklingError: Can't pickle <type 'weakref'>: it's not found as __builtin__.weakref

我缺少什么或不理解?我也尝试过实施__getstate__() / __setstate__(state)组合,结果相同。

2 个答案:

答案 0 :(得分:7)

你绝对可以挑选weakref,你可以挑选dictlist。 然而,实际上它们包含的内容很重要。如果dictlist包含不可推断的intems,则酸洗将失败。如果您要挑选weakref,则必须使用dill而不是pickle。然而,未被删除的weakref反序列化为死引用。

>>> import dill
>>> import weakref
>>> dill.loads(dill.dumps(weakref.WeakKeyDictionary()))
<WeakKeyDictionary at 4528979192>
>>> dill.loads(dill.dumps(weakref.WeakValueDictionary()))
<WeakValueDictionary at 4528976888>
>>> class _class:
...   def _method(self):
...     pass
... 
>>> _instance = _class()
>>> dill.loads(dill.dumps(weakref.ref(_instance)))
<weakref at 0x10d748940; dead>
>>> dill.loads(dill.dumps(weakref.ref(_class())))
<weakref at 0x10e246a48; dead>
>>> dill.loads(dill.dumps(weakref.proxy(_instance)))
<weakproxy at 0x10e246b50 to NoneType at 0x10d481598>
>>> dill.loads(dill.dumps(weakref.proxy(_class())))
<weakproxy at 0x10e246ba8 to NoneType at 0x10d481598>

答案 1 :(得分:3)

我通过在__getstate__ / __setstate__中切换弱/强引用来解决这个问题:

class DBObject(object):
    def __getstate__(self):
        s = self.__dict__.copy()
        s['_db'] = s['_db']()
        return s

    def __setstate__(self, state):
        self.__dict__ = state.copy()
        self.__dict__['_db'] = weakref.ref(self.__dict__['_db'])