Domanda

Sto lavorando a un progetto in cui abbiamo un gran numero di oggetti che vengono serializzati e conservati sul disco utilizzando pickle/cPickle.

Man mano che la vita del progetto avanza (dopo il rilascio ai clienti sul campo), è probabile che le caratteristiche/correzioni future ci richiederanno di cambiare la firma di alcuni dei nostri oggetti persistiti. Questa potrebbe essere l'aggiunta di campi, la rimozione di campi o anche solo cambiare gli invarianti su un dato.

Esiste un modo standard per contrassegnare un oggetto che sarà sottaceto come una determinata versione (come serialVersionUID in java)? Fondamentalmente, se sto ripristinando un'istanza di Foo versione 234 ma il codice corrente è 236, voglio ricevere una notifica su difetto. Dovrei semplicemente andare avanti e lanciare la mia soluzione (potrebbe essere una pita).

Grazie

È stato utile?

Soluzione

Il pickle Il formato non ha tale condizione. Perché non fai semplicemente la parte "Numero di versione seriale" degli attributi dell'oggetto, per essere in salamoia insieme al resto? Quindi la "notifica" può essere banale confrontando la versione effettiva e desiderata - non capire perché dovrebbe essere una pita.

Altri suggerimenti

Considera il seguente mixin di classe suggerito da Tomasz Früboes qui.

# versionable.py
class Versionable(object):
    def __getstate__(self):
        if not hasattr(self, "_class_version"):
            raise Exception("Your class must define _class_version class variable")
        return dict(_class_version=self._class_version, **self.__dict__)
    def __setstate__(self, dict_):
        version_present_in_pickle = dict_.pop("_class_version")
        if version_present_in_pickle != self._class_version:
            raise Exception("Class versions differ: in pickle file: {}, "
                            "in current class definition: {}"
                            .format(version_present_in_pickle,
                                    self._class_version))
        self.__dict__ = dict_

Il __getstate__ Il metodo è chiamato da pickle al decapaggio e __setstate__ è chiamato da sottaceto su uno stanco. Questa classe mix-in può essere utilizzata come sottoclasse di classi di cui si desidera tenere traccia. Questo deve essere usato come segue:

# bla.py
from versionable import Versionable
import pickle

class TestVersioning(Versionable):
    _class_version = 1

t1 = TestVersioning()

t_pickle_str = pickle.dumps(t1)

class TestVersioning(Versionable):
    _class_version = 2

t2 = pickle.loads(t_pickle_str) # Throws exception about wrong class version
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top