序列化链接对象

13 投票
3 回答
3447 浏览
提问于 2025-04-16 19:43

我想把一个对象和一个引用了第一个对象的第二个对象进行序列化(也就是“腌制”)。但是当我简单地进行序列化和反序列化时,这个引用就变成了一个复制品。请问我该如何保持这两个对象 foobar.foo_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)

3 个回答

0

好吧,你可以这样做:

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

让pickle来处理这个链接吧。

1

如果你把它们一起进行序列化(也就是用“腌制”这个方法),那么序列化模块会记录引用,只会把 foo 这个变量腌制一次。你能像这样同时腌制 foobar 吗?

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
7

我之前的回答没有抓住你的重点。你代码的问题在于你没有使用PicklerUnpickler这两个对象。下面是一个可以正常工作的版本,里面有多个存储调用:

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

撰写回答