Per ottenere vantaggi dalla persistenza degli oggetti, il modulo pickle supporta la nozione relativa di un riferimento ad un oggetto esterno al flusso dei dati serializzati. Questi oggetti vengono riferiti tramite un ``id persistente'', che consiste in una stringa arbritraria di caratteri ASCII stampabili. La risoluzione di questi nomi non viene definita dal modulo pickle, ma viene delegata alle funzioni definite dall'utente su pickler ed unpickler.3.8
Per definire esternamente la risoluzione di un id persistente, si ha bisogno di impostare l'attributo persistent_id nell'oggetto serializzatore, e l'attributo persistent_load dell'oggetto deserializzatore.
Per serializzare oggetti che hanno un id persistente esterno, il
pickler deve avere un metodo personalizzato persistent_id()
che prenda un oggetto come un argomento e restituisca o None
oppure l'id persistente per quell'oggetto. Quando viene restituito
None
, il pickler semplicemente serializza l'oggetto come normale.
Quando viene restituita una stringa di id persistente, il pickler
serializzerà quella stringa attraverso un marcatore, così che il
deserializzatore riconosca la stringa come id persistente.
Per deserializzare oggetti esterni, il deserializzatore deve avere una funzione personalizzata persistent_load(), che prenda una stringa id persistente e restituisca l'oggetto referenziato.
Ecco uno sciocco esempio che potrebbe fare un po' di luce:
import pickle from cStringIO import StringIO src = StringIO() p = pickle.Pickler(src) def persistent_id(obj): if hasattr(obj, 'x'): return 'il valore %d' % obj.x else: return None p.persistent_id = persistent_id class Integer: def __init__(self, x): self.x = x def __str__(self): return 'Il mio nome e` intero %d' % self.x i = Integer(7) print i p.dump(i) datastream = src.getvalue() print repr(datastream) dst = StringIO(datastream) up = pickle.Unpickler(dst) class FancyInteger(Integer): def __str__(self): return 'Io sono il numero %d' % self.x def persistent_load(persid): if persid.startswith('the value '): value = int(persid.split()[2]) return FancyInteger(value) else: raise pickle.UnpicklingError, 'ID persistente non valido' up.persistent_load = persistent_load j = up.load() print j
Nel modulo cPickle, l'attributo persistent_load dell'unpickler può anche venire impostato su una lista Python, nel qual caso, quando l'unpickler incontra un id persistente, la sua stringa id viene semplicemente accodata a tale lista. Questa funzionalità esiste per far sì che un flusso di dati serializzati possa venire ``sniffato'' alla ricerca di riferimenti ad oggetti senza istanziare effettivamente tutti gli oggetti serializzati.3.9L'impostazione di persistent_load su una lista viene di solito usata congiuntamente a un metodo noload() nell'Unpickler.