Python Pickle链接对象

Python Pickle链接对象,python,pickle,Python,Pickle,我想pickle一个对象和引用第一个对象的第二个对象。当我天真地pickle/unpickle这两个对象时,引用就变成了一个副本。如何保留两个对象foo和bar.foo\u ref之间的链接 import pickle class Foo(object): pass foo = Foo() bar = Foo() bar.foo_ref = foo with open('tmp.pkl', 'wb') as f: pickle.dump(foo, f) pickle

我想pickle一个对象和引用第一个对象的第二个对象。当我天真地pickle/unpickle这两个对象时,引用就变成了一个副本。如何保留两个对象
foo
bar.foo\u ref
之间的链接

import pickle

class Foo(object):
    pass

foo = Foo()
bar = Foo()
bar.foo_ref = foo

with open('tmp.pkl', 'wb') as f:
    pickle.dump(foo, f)
    pickle.dump(bar, f)
with open('tmp.pkl', 'rb') as f:
    foo2 = pickle.load(f)
    bar2 = pickle.load(f)

print id(foo) == id(bar.foo_ref) # True
print id(foo2) == id(bar2.foo_ref) # False
# want id(foo2) == id(bar2.foo_ref)
那么,你能做到:

bar2 = pickle.load(f)
foo2 = bar2.foo_ref

让pickle为您处理链接。

如果将它们一起pickle,pickle模块将跟踪引用,并且只对
foo
变量pickle一次。你能像这样把
foo
bar
一起腌制吗

import pickle

class Foo(object):
    pass

foo = Foo()
bar = Foo()
bar.foo_ref = foo

with open('tmp.pkl', 'wb') as f:
    pickle.dump((foo, bar), f)
with open('tmp.pkl', 'rb') as f:
    foo2, bar2 = pickle.load(f)

print id(foo) == id(bar.foo_ref) # True
print id(foo2) == id(bar2.foo_ref) # True

我先前的回答没有抓住你的重点。代码的问题在于没有使用
Pickler
Unpickler
对象。以下是一个具有多个转储调用的工作版本:

import pickle

class Foo(object):
    pass

foo = Foo()
bar = Foo()
bar.foo_ref = foo

f = open('tmp.pkl', 'wb')
p = pickle.Pickler(f)
p.dump(foo)
p.dump(bar)
f.close()

f = open('tmp.pkl', 'rb')
up = pickle.Unpickler(f)
foo2 = up.load()
bar2 = up.load()

print id(foo) == id(bar.foo_ref) # True
print id(foo2) == id(bar2.foo_ref) # True

我认为您不能在不同的pickle中保存对象标识。如果您有一个包含foo和bar的主对象x,并对其进行了pickle,那么根据文档,当您取消pickle它的id(x.foo)==id(x.bar.foo_ref)时,应该没有必要这样做,因为
pickle
应该跟踪它已序列化的对象,并且在引用已序列化的对象时不会重复。@JAB我认为这只是一次对dump的调用,而不是对同一文件多次对dump的调用?这是可行的,但如果您希望能够多次调用dump,您可以使用
Pickler
Unpickler
对象来实现这一点。有关详细信息,请参阅我的其他答案。谢谢,但我不想手动处理引用层次结构。这是我的怀疑,当我注意到文档中指出只有
Pickler
/
Unpickler
类的实例具有用于跟踪pickle/unpickle对象的
memo
属性时,我证实了这一点。简单有效。谢谢