2011-06-16 11 views
10

Quiero recortar un objeto y un segundo objeto que hace referencia al primero. Cuando inocentemente saco/desenrollo los dos objetos, la referencia se convierte en una copia. ¿Cómo guardo el enlace entre los dos objetos foo y bar.foo_ref?Objetos vinculados a salmuera

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

No creo que pueda preservar la identidad del objeto en diferentes escapes. Si tenía un objeto maestro x que incluía foo y barra, y lo decapaba, cuando lo desató Id (x.foo) == id (x.bar.foo_ref) – antlersoft

Respuesta

5

Mi respuesta anterior faltaba su punto. El problema con su código es que no está utilizando los objetos Pickler y Unpickler. Aquí hay una versión funcional con varias llamadas de volcado:

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

Esa fue mi sospecha, confirmada cuando me di cuenta de que la documentación indica que solo las instancias de las clases 'Pickler' /' Unpickler' tienen un atributo 'memo' utilizado para realizar un seguimiento de los objetos en escabeche/sin desbastar. http://docs.python.org/library/pickle.html#pickle.Pickler.clear_memo – JAB

+0

Simple y eficaz. ¡Gracias! – matt

0

Bueno, ¿puedes hacer:

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

Deje salmuera manejar el enlace para usted.

+0

Gracias, pero preferiría no manejar la jerarquía de referencia manualmente . – matt

1

Si los combina, el módulo de pickle realiza un seguimiento de las referencias y solo encuadra la variable foo una vez. ¿Puedes juntar foo y bar juntos, así?

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

Según la documentación, eso no debería ser necesario, ya que 'pickle' se supone que realiza un seguimiento de los objetos que ha serializado y no vuelve a procesar cuando se hacen referencias a objetos ya serializados. – JAB

+0

@JAB Pensé que era solo con una sola llamada para volcar, no múltiples llamadas para volcar en el mismo archivo? – jterrace

+0

Pero funciona ... –

Cuestiones relacionadas