2010-06-08 20 views
16

Sto utilizzando gnosis.xml.pickle per convertire un oggetto della mia classe in xml. L'oggetto viene inizializzato in modo che:Come interrompere il declassamento degli attributi in Python

self.logger = MyLogger() 

Ma quando faccio il dump l'oggetto in una stringa ottengo un'eccezione che indica che il pickler rilevato un tipo unpickleable (thread.lock).

C'è un modo per 'tag' l'attributo logger in modo che il pickler sappia di non provare a decapitare quell'attributo?

risposta

29

È possibile definire due metodi, __getstate__ e __setstate__, nella classe per sovrascrivere il comportamento di decapaggio predefinito.

http://docs.python.org/library/pickle.html#object.__getstate__

__getstate__ dovrebbe restituire un dict di attributi che si desidera salamoia.

def __getstate__(self): 
    d = dict(self.__dict__) 
    del d['logger'] 
    return d 

__setstate__ necessario impostare l'oggetto con il dict fornito.

def __setstate__(self, d): 
    self.__dict__.update(d) # I *think* this is a safe way to do it 

Nota che __init__ non verrà chiamato quando deserializzazione quindi dovrete creare il vostro logger in __setstate__

+0

grazie. per favore nota che sto usando la gnosis pickle lib, non sono sicuro che funzionerebbe allo stesso modo? – Ries

+0

Ho cercato su Google la fonte di gnosis e ho visto le chiamate per ottenerestate e impostare lo stato, quindi penso che funzionerà. – FogleBird

+0

Questo ha funzionato perfettamente per me, grazie! – amirpc

3

La classe può implementare il metodo speciale __getstate__ per restituire esattamente le parti di un'istanza che desidera sottoporre a decapaggio.

ci sono diverse varianti possibili su quella (anche se __getstate__ e la sua compagna opzionale metodo __setstate__ sono più generale) - si veda la pagina doc Python on-line per pickle, a cui ho già accennato in precedenza, perché è quello che documenta __getstate__.

+0

grazie. idealmente mi piacerebbe solo specificare cosa NON voglio sottaceto. – Ries

+1

@Ries, esegue il loop su tutti i membri (utilizzando inspect.getmembers, l'istanza '__dict__', qualsiasi cosa) e rimuove quelli che si desidera rimuovere. Non esiste un metodo speciale '__donotsavetheseones_', devi implementarlo come' __getstate__'. –

3

Questa potrebbe essere una soluzione migliore in quanto consentirà un oggetto creato tramite copy.deepcopy a ancora un auto.logger

def __getstate__(self): 
    d = self.__dict__.copy() 
    if 'logger' in d.keys() 
     d['logger'] = d['logger'].name 
    return d 

def __setstate__(self, d): 
    if 'logger' in d.keys(): 
     d['logger'] = logging.getLogger(d['logger']) 
    self.__dict__.update(d) 
Problemi correlati