2016-05-04 6 views
0

Angenommen, wir haben ein Objekt, das wir unter Verwendung von pickle in eine Binärdatei schreiben. Lassen Sie uns sagen, dass das Objektgraph wie folgt aussieht:Wie man ein Essiggurken-Objekt lädt und bestimmte Referenzen auflöst

foo1 
+--->bar 
|  \--->context 
+--->baz 
|  +--->context 
|  \--->qux 
\--->context 

Jetzt sind die context Objekte sind große Datenstrukturen und alle Instanzen von qux sind die gleichen. Deshalb haben wir beschlossen, mit diesen contexxt Objekte aus dem Beize Prozesses zu verlassen:

def __getstate__(self): 
    my_dict = dict(self.__dict__) 
    my_dict['context'] = None # We don't save the context 
    return my_dict 

für die Klassen, zu denen foo, bar und baz gehören (und in der Tat alle anderen Klassen in unserem Design).

Wenn wir load() das Objekt zurück in den Speicher, wollen wir alle context Referenzen auf unseren gegebenen Kontext zurückgesetzt werden. Man kann dies tun, indem man rekursiv über den Objektbaum geht, aber wir fragen uns, ob es eine elegantere Lösung in pickle gibt, die die context Werte selbst ausfüllt, wenn die Daten zurück in den Speicher geladen werden?

+0

Sie suchen, [ '__setstate__'] (https : //docs.python.org/3/library/pickle.html#object.__setstate__) oder fehle ich etwas? –

+1

@ IljaEverilä: Das Problem ist, dass '__setstate__' keine zusätzlichen Parameter hat, so dass wir den Kontext zurücksetzen können. Nichtsdestotrotz glaube ich, dass ich eine Antwort in * hartnäckigem Beizen * (https://docs.python.org/3.2/library/pickle.html#pickle-persistent) gefunden habe. –

+1

Schön, wusste nicht davon (Verweis auf externe Objektunterstützung). Dein eigener Befund scheint der richtige Weg zu sein. –

Antwort

2

Wenn die .context vom Typ Context, statt context-None Einstellung, könnten Sie den Code aus dem Abschnitt Persistence of External Objects in der pickle Dokumentation anpassen:

import pickle 

class ContextAwarePickler(pickle.Pickler): 
    def persistent_id(self, obj): 
     # if this is a context, return the key 
     if isinstance(obj, Context): 
      return ("Context", context.key) 

     # pickle as usual 
     return None 


class ContextAwareUnpickler(pickle.Unpickler): 
    def recover_context(self, key_id): 
     ... 

    def persistent_load(self, pid): 
     type_tag, key_id = pid 
     if type_tag == "Context": 
      return self.recover_context(key_id) 
     else: 
      raise pickle.UnpicklingError("unsupported persistent object") 
+0

Danke. Ein paar Minuten nachdem ich die Frage gestellt hatte, fand ich das Beispiel. Der geänderte Code erleichtert jedoch das Verständnis. +1. –

Verwandte Themen