2013-04-28 10 views
7

Nachdem eine Klassendefinition durch Neukompilieren eines Skripts aktualisiert wurde, verweigert die Beize das vorherige Serialisieren zuvor instantiierter Objekte dieser Klasse und gibt den Fehler: "Kann kein Objekt pürieren: Es ist nicht dasselbe Objekt wie "Python-Beize: Umgang mit aktualisierten Klassendefinitionen

Gibt es eine Möglichkeit, Pickle zu sagen, dass es solche Fälle ignorieren sollte? Um nur Klassen nach Namen zu identifizieren, ignorieren Sie die interne eindeutige ID, die die Nichtübereinstimmung verursacht.

Ich würde definitiv als Antwort die Anregung eines alternativen, äquivalenten Moduls begrüßen, das dieses Problem in einer bequemen und robusten Weise löst.


Als Referenz ist hier meine Motivation:

ich eine hohe Produktivität, Umwelt schnelle Iteration Entwicklung erschaffe, in der Python-Skripte Live bearbeitet werden. Skripts werden wiederholt neu kompiliert, aber Daten bleiben über Kompilierungen erhalten. Als Teil der Produktivitätsziele versuche ich Pickle für die Serialisierung zu verwenden, um die Kosten für das Schreiben und Aktualisieren von explizitem Serialisierungscode für sich ständig ändernde Datenstrukturen zu vermeiden.

Meistens serialisiert ich eingebaute Typen. Ich achte darauf, bedeutungsvolle Änderungen in den Klassen zu vermeiden, die ich pickele, und wenn nötig, benutze ich den Mechanismus copy_reg.pickle, um die Aufwärtskonvertierung beim Unpickle durchzuführen.

Die Neukompilierung von Skripten verhindert, dass ich Objekte überhaupt beize, auch wenn die Klassendefinitionen sich nicht wirklich geändert haben (oder sich nur gutartig geändert haben).

+1

Ich habe nicht viel Zeit damit verbracht, aber das kann nützlich sein: http://docs.python.org/2/library/pickle.html#pickling-and-unpickling-normal-class-instances – mgilson

Antwort

0

Zwei Lösungen kommen mir in den Sinn:

  1. , bevor Sie Sie Pickles Vielleicht object.__class__

    >>> class X(object): 
        pass 
    
    >>> class Y(object): 
        pass 
    
    >>> x = X() 
    >>> x.__class__ = Y 
    >>> type(x) 
    <class '__main__.Y'> 
    

    einstellen können Sie persistent_id für das, weil jeder übergebene Objekt wird verwenden können.

  2. define __reduce__ genau dasselbe wie Gurke tut. (Einen Blick auf pickle.py dafür haben)

6

Wenn Sie die frühere Version der Klassendefinition entpacken können, muss die Referenz Beize dump und laden die Instanz ist jetzt weg. Das ist also "nicht möglich".

Wenn Sie es jedoch tun möchten, könnten Sie vorherige Versionen Ihrer Klassendefinitionen speichern ... und dann wäre es nur, dass Sie Pickle in Beziehen auf Ihre alte/gespeicherte Klasse Trick müssen Definitionen, und nicht mit den neuesten - das könnte nur Bearbeitung obj.__class__ oder obj.__module__ auf Ihre alte Klasse zeigen. Es kann auch einige andere seltsame Dinge in Ihrer Klasseninstanz geben, die sich auch auf die alte Klassendefinition beziehen, die Sie behandeln müssten. Wenn Sie eine Klassenmethode hinzufügen oder löschen, führen Sie möglicherweise unerwartete Ergebnisse ein oder müssen die Instanz entsprechend aktualisieren. Ein weiterer interessanter Aspekt ist, dass Sie den Unpickler immer die aktuellste Version Ihrer Klasse verwenden lassen können.

Mein Serialisierungspaket, dill, verfügt über einige Methoden, die kompilierte Quelle aus einem Live-Code-Objekt in eine temporäre Datei speichern und dann mit dieser temporären Datei serialisieren können. Es ist einer der neueren Teile des Pakets, also ist es nicht so robust wie der Rest von Dill.Auch Ihr Anwendungsfall ist kein Anwendungsfall, den ich in Betracht gezogen hätte, aber ich könnte sehen, wie es ein nettes Feature wäre.

+0

Ok , Ich habe diese Funktion zu Dill in der neuesten Revision auf Github hinzugefügt. Implementiert mit weit weniger Tricks als ich dachte ... einfach die Klassendefinition mit der Beize serialisieren, und voila. –