2017-04-13 4 views
1

Ich möchte Pickle verwenden, insbesondere cPickle, um die Daten meiner Objekte als Ordner von Dateien zu katalogisieren, die Module, Projekte, Modulobjekte, Szenenobjekte usw. darstellen. Gibt es einen einfachen Weg, dies zu tun?Wie pickel ich eine Objekthierarchie, * jedes Objekt normalerweise eine eigene Datei *, so dass das Speichern schnell ist?

Das erneute Öffnen ist also ein wenig schwierig, da jedes übergeordnete Objekt einen Verweis auf untergeordnete/untergeordnete Objekte speichert, während die Pickle-Daten des übergeordneten Elements einen Dateipfad zum Objekt enthalten.

Ich begann mit einer PathUtil-Klasse, die alle Klassen erben, aber Probleme aufgetreten sind. Hat jemand ein ähnliches Problem/Feature der Dateispeicherung/Wiederherstellung gelöst?

Je transparenter es mit vorhandenem Code funktioniert, desto besser. Wenn beispielsweise die Verwendung einer Metaklasse __call__ dazu führt, dass die vorhandene Konstruktorsyntax gleich bleibt, ist das ein Plus. Zum Beispiel wird die statische __call__ die Beizdatei zuerst prüfen und laden es, wenn es existiert, während eine Standardkonstruktion, wenn es nicht tut.

+0

Ich denke '__reduce__' könnte hier gut verwendet werden. –

Antwort

1

Sie können __getstate__ überschreiben, um in eine neue Beizdatei zu schreiben und ihren Pfad zurückzugeben, und __setstate__, um die Datei zu entpacken.

import pickle, os 

DIRNAME = 'path/to/my/pickles/' 

class AutoPickleable: 

    def __getstate__(self): 
     state = dict(self.__dict__) 
     path = os.path.join(DIRNAME, str(id(self))) 
     with open(path, 'wb') as f: 
      pickle.dump(state, f) 
     return path 

    def __setstate__(self, path): 
     with open(path, 'b') as f: 
      state = pickle.load(f) 
     self.__dict__.update(state) 

nun jede Art, die diese besonderen Auto-pickleable Verhalten haben sollte, sollte AutoPickleable Unterklasse. Wenn Sie die Dateien ausgeben möchten, können Sie pickle.dumps(obj) oder copy.deepcopy(obj) tun und das Ergebnis ignorieren.

Das Abnehmen funktioniert wie gewohnt (pickle.load). Wenn Sie die Objekte aus einem Dateipfad (und nicht aus den Ergebnissen von pickle.dumps) wiederherstellen möchten, ist es ein wenig komplizierter. Lass es mich wissen, wenn du es willst, und ich werde Details hinzufügen. In jedem Fall, wenn Sie Ihr AutoPickleable Objekt mit einem "Standard" -Objekt umhüllen und alle Pickle-Operationen darauf ausführen, sollte alles funktionieren.

Es gibt mehrere mögliche Probleme mit diesem Ansatz, aber für einen "sauberen" Fall wie den, den Sie beschreiben, könnte es funktionieren.

Einige Anmerkungen:

  • Es gibt keine Art und Weise ist es, „dynamisch“ das Verzeichnis angeben, um zu schreiben. Es muss global zugänglich sein und vor dem Beizen gesetzt werden
  • Wahrscheinlich würde nicht funktionieren, wenn mehrere Objekte Referenzen auf das gleiche AutoPickleable Objekt, oder wenn Sie Zirkelverweise haben (im Allgemeinen, pickle behandeln diese Fälle ohne Problem)
  • Es gibt keinen Code, um das Verzeichnis zu bereinigen/löschen Sie die Dateien.
+1

Ich mag, wie '__getstate__' den Pfad zurückgibt. Da ich immer mit Vererbungsproblemen bei PyQt5 zu tun habe, werde ich dies nicht ableiten, sondern irgendwie ein Mitglied machen –

Verwandte Themen