2010-06-08 14 views
16

Ich benutze gnosis.xml.pickle, um ein Objekt meiner eigenen Klasse in XML zu konvertieren. Das Objekt wird so initialisiert, dass:Wie zu verhindern, dass Attribute in Python gebeizt werden

self.logger = MyLogger() 

Aber wenn ich das Objekt in einen String tun Dump erhalte ich eine Ausnahme besagt, dass die Beize einen unpickleable Typen (thread.lock) angetroffen.

Gibt es eine Möglichkeit, das Logger-Attribut zu "taggen", so dass der Abbeizer weiß, dass er dieses Attribut nicht pürieren muss?

Antwort

29

Sie können zwei Methoden, __getstate__ und __setstate__, für Ihre Klasse definieren, um das standardmäßige Beizverhalten zu überschreiben.

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

__getstate__ sollte ein dict von Attributen zurückgeben, die Sie beizen möchten.

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

__setstate__ sollte Setup Ihr ​​Objekt mit dem mitgelieferten dict.

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

Beachten Sie, dass __init__ nicht in Anspruch genommen werden, wenn Unpickling so werden Sie Ihre Logger in __setstate__

+0

danke. Bitte beachten Sie, dass ich die gnosis pickle lib verwende, nicht sicher, ob es gleich funktionieren würde? – Ries

+0

Ich googelte für die Gnosis-Quelle und sah Aufrufe zum Setzen und Setzen, also denke ich, dass es funktionieren wird. – FogleBird

+0

Das hat perfekt für mich funktioniert, danke! – amirpc

3

Ihre Klasse kann die spezielle Methode __getstate__ implementieren, um genau die Teile einer Instanz zurückzugeben, für die sie gebeizt werden soll.

Es gibt mehrere mögliche Varianten auf, dass (obwohl __getstate__ und seiner optionalen Begleiter Methode __setstate__ allgemeinste sind) - finden Sie in der Online-Python doc Seite für pickle, auf die ich oben bereits erwähnt, weil es derjenige ist dokumentiert __getstate__.

+0

danke. idealerweise möchte ich nur angeben müssen, was ich nicht pickle. – Ries

+1

@Ries, Schleife über alle Mitglieder (mit inspect.getmembers, der '__dict__' der Instanz, was auch immer) und entfernen Sie diejenigen, die Sie entfernen möchten. Es gibt keine spezielle Methode "__donotsavetheseones_", die Sie als '__getstate__' implementieren müssen. –

3

Diese zu schaffen haben könnte, eine bessere Lösung sein, da es ein Objekt ermöglicht über copy.deepcopy erstellt habe noch einen self.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) 
Verwandte Themen