2011-06-16 52 views
10

我想泡菜一個對象和第二個對象,引用第一個。當我天真地醃製/取下這兩個物體時,參考變成了一個副本。如何保留兩個對象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) 
+0

我不認爲你可以保留跨單獨泡菜對象的身份。如果您有一個包含foo和bar的主對象x,並對它進行了pickle操作,當您取消對它的id(x.foo)== id(x.bar.foo_ref) – antlersoft 2011-06-16 17:43:53

回答

5

我以前的回答錯過了你的觀點。你的代碼的問題是你沒有使用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 
+2

這是我的懷疑,當我發現文檔指出只有'Pickler' /'Unpickler'類的實例具有用於跟蹤pickled/unpickled對象的'memo'屬性時才確認。 http://docs.python.org/library/pickle.html#pickle.Pickler.clear_memo – JAB 2011-06-16 18:00:22

+0

簡單而有效。謝謝! – matt 2011-06-16 18:09:25

0

嗯,你可以這樣做:

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

讓泡菜處理環節爲您服務。

+0

謝謝,但我寧願不手動處理參考層次。 – matt 2011-06-16 17:47:34

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 
+0

根據文檔,這不應該是必要的,因爲'pickle'應該跟蹤它已經序列化的對象,並且在已經序列化的對象被引用時不會重新啓動。 – JAB 2011-06-16 17:44:27

+0

@JAB我認爲這只是一個調用轉儲,而不是多個調用轉儲在同一個文件? – jterrace 2011-06-16 17:45:19

+0

但它有效...... – 2011-06-16 17:45:36