New style classes und pickle

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hallo.
Ich habe versucht eine new style klasse, die __slots__ definiert mit pickle zu serialisieren, aber das geht nicht? Wieso?

grüße,
Leonidas
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Zeig doch bitte mal etwas Quellcode. Ohne können wir nur ins blaue raten... :wink:
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Der Code ist:

Code: Alles auswählen

class Settings(object):
    # what is __getstate__ ?
    #__slots__ = ['wordmode', 'casemode', 'errormode', 'searchmode', 'debug', 'showparabar', 'showumlautbar']
    def __init__(self, wordmode='full', casemode='ignore',\
            errormode='0error', searchmode='simple',\
            showparabar=False, showumlautbar=False, debug=False):
        """This constructor is able to set up nearly everything"""
        self.wordmode = wordmode
        self.casemode = casemode
        self.errormode = errormode
        self.searchmode = searchmode
        self.showparabar = showparabar
        self.showumlautbar = showumlautbar
        self.debug = debug
    
    def SetWordmode(self, wordmode):
        """Changes the wordmode in the settings after it is verified"""
        if wordmode == 'full' or wordmode == 'partial':
            self.wordmode = wordmode
        else:
            raise ValueError('No such wordmode allowed: %s' % wordmode)
    
    def GetWordmode(self):
        """Returns the wordmode"""
        return self.wordmode
    
    def SetCasemode(self, casemode):
        """Changes the casemode in the settings after it is verified"""
        if casemode == 'exact' or casemode == 'ignore':
            self.casemode = casemode
        else:
            raise ValueError('No such casemode allowed: %s' % casemode)
    
    def GetCasemode(self):
        """Returns the casemode"""
        return self.casemode
    
    def SetErrormode(self, errormode):
        """Changes the errormode in the settings after it is verified"""
        if errormode == '0error' or errormode == '1error' or errormode == '2error' or errormode == '3error' or errormode == '4error' or errormode == 'bestmatch':
            self.errormode = errormode
        else:
            raise ValueError('No such errormode allowed: %s' % errormode)
    
    def GetErrormode(self):
        """Returns the errormode"""
        return self.errormode
    
    def SetSearchmode(self, searchmode):
        """Changes the searchmode in the settings after it is verified"""
        if searchmode == 'simple' or searchmode == 'regex':
            self.searchmode = searchmode
        else:
            raise ValueError('No such searchmode allowed: %s' % searchmode)
    
    def GetSearchmode(self):
        """Returns the searchmode"""
        return self.searchmode
Ich habe hier slots auskommentiert, dann geht es, aber ich will die ja nutzen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Ich hab mich jetzt nocheinmal durch die Docu's gewühlt... wie es ausschaut müssen new-style Klassen die Methoden __getstate__ und __setstate__ implementieren (hier das ganze als anderes Bsp.) Die regeln dann, was gepickelt wird und was nicht. So kann also __getstate__ ein Dict mit allen wichtigen Werten übergeben (also alles, was in __slots__ steht) und dann wird das Dict gepickelt. Beim unpickeln wird dann __setstate__ mit dem Dict gerufen und dann werden einfach alle Werte wieder gesetzt. Nicht gerade komfortabel, aber machbar. Bsp:

Code: Alles auswählen

class test(object):
    __slots__=["x"]
    def __init__(self,x):
        self.x=x
    def __getstate__(self):
        erg={}
        for i in self.__slots__:
            erg[i]=getattr(self,i)
        return erg
    def __setstate(self,dict):
        for i in dict:
            setattr(self,i,dict[i])
hth, Milan
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

also ich habe mal folgendes gemacht:
- slots wieder 'einkommentiert'
- folgenden code eingebaut (und nur den):

Code: Alles auswählen

def __getattr__(self):
    return self.__slots__
Damit scheint es zu gehen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Das würde ich aber auf keinen Fall machen... probier mal Settings().wordmode zu rufen, dass dürfte nun einen Fehler geben (sofern du nicht von object ableitest. Dann wird intern __getattribute__ statt __getattr__ gerufen). Aber trotzdem ist __getattr für was anderes da, als eine Liste (nicht definiert, da __slots__ auskommentiert) zurückzugeben.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du hast recht (es geht schon beim unpickeln nicht...). Deswegen habe ich mal deinen COde eingebaut:

Code: Alles auswählen

def __getstate__(self):
        erg={}
        for i in self.__slots__:
            erg[i]=getattr(self,i)
        return erg
Da kommt aber dann:

Code: Alles auswählen

Traceback (most recent call last):
  File "c:\ding.py", line 1157, in ?
    conf = pickle.load(file(picklename))
  File "C:\PROGRA~1\Python\Lib\pickle.py", line 1390, in load
    return Unpickler(file).load()
  File "C:\PROGRA~1\Python\Lib\pickle.py", line 872, in load
    dispatch[key](self)
  File "C:\PROGRA~1\Python\Lib\pickle.py", line 1244, in load_build
    inst.__dict__.update(state)
AttributeError: 'Settings' object has no attribute '__dict__'
Was kann ich dann machen?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Gast

Da muss man das neue pickle protokol verwenden, das noch nicht standart ist...

http://docs.python.org/lib/node64.html

Da musst du als protokol 2 nehmen (pickle.HIGHEST_PROTOCOL)

also zb dumps(objekt,2)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

also mit dump(..., pickle.HIGHTEST_PROTOCOL) gibt es den gleichen fehler.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten