Speichern einer Klasse

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
Pythoraner123
User
Beiträge: 23
Registriert: Dienstag 25. Dezember 2012, 16:43

Hallo,
ich bin dabei ein rollenspiel zu programmieren.
Nun will ich die ganzen Dateien (level, name usw) mit dem modul pickle abspeichern.
Dies funktioniert nicht und ich bekomme folgende Fehlermeldung

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python32\Programme\Rollenspiel.py", line 163, in <module>
    charakter_daten_liste=pickle.load(datei)
TypeError: 'str' does not support the buffer interface
Wie schaffe ich es das zu vermeiden?
Danke schon mal im Voraus
BlackJack

@Pythoraner123: `load()` ist zum laden und nicht zum Speichern.

Ansonsten wäre der relevante Quelltext zur Fehlermeldung und der *komplette* Traceback hilfreich.
Pythoraner123
User
Beiträge: 23
Registriert: Dienstag 25. Dezember 2012, 16:43

Ne das Problem trat beim laden auf
Für das Speichern hab ich eine Funktion verwendet

Code: Alles auswählen

def speichern(charakter):
    datei=open("gespeicherte_charakterdaten.pkl", "w")
    charakakter_daten_liste=[charakter.name, charakter.leben, charakter.angriffskraft, charakter.level, charakter.erfahrung, charakter.erforderliche_xp, charakter.gold]
    datei.close()
Laden im Hauptprogramm:

Code: Alles auswählen

datei=open("gespeicherte_charakterdaten.pkl", "r")
charakter_daten_liste=pickle.load(datei)
c1=Charakter("Name")#Mehr als den Namen braucht man nicht
c1.laden(charakter_daten_liste, datei)
Fehlermeldung(war komplett):

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python32\Programme\Rollenspiel.py", line 163, in <module>
    charakter_daten_liste=pickle.load(datei)
TypeError: 'str' does not support the buffer interface
Tris
User
Beiträge: 1
Registriert: Freitag 29. Juni 2012, 06:41

Du musst binär speichern/öffnen mit pickle.
Sprich, aus
datei=open("gespeicherte_charakterdaten.pkl", "w")
wird
datei=open("gespeicherte_charakterdaten.pkl", "wb")
Sirius3
User
Beiträge: 18319
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Pythoraner123,

wo schreibst Du in

Code: Alles auswählen

def speichern(charakter):
    datei=open("gespeicherte_charakterdaten.pkl", "w")
    charakakter_daten_liste=[charakter.name, charakter.leben, charakter.angriffskraft, charakter.level, charakter.erfahrung, charakter.erforderliche_xp, charakter.gold]
    datei.close()
irgendwas in die Datei?
Du öffnest und schließt sie nur. Sollte Dir auch an der Dateigröße (0) auffallen.

Bei pickle kann man ganze Objekte speichern und muß sich nicht extra Lade- und Schreib-Routinen selbst bauen:

Code: Alles auswählen

with open("gespeicherte_charakterdaten.pkl", "wb") as datei:
    pickle.dump(charakter, datei)

Code: Alles auswählen

with open("gespeicherte_charakterdaten.pkl", "rb") as datei:
    charakter=pickle.load(datei)

Grüße
Sirius
Pythoraner123
User
Beiträge: 23
Registriert: Dienstag 25. Dezember 2012, 16:43

So es klappt jetzt...
Danke für die Hilfe.
BlackJack

An der Stelle vielleicht noch der Hinweis, dass man nichts in Pickle-Dateien sichern sollte, was man potentiell lange aufheben will und nicht 100%ig sicher ist, dass sich die gespeicherten Datentypen nicht mehr verändern. Es werden nur die Daten selbst gespeichert und die Namen der Datentypen, dass heisst wenn man an denen inhaltlich zu viel ändert, oder sie einfach nur umbenennt oder die Paketstruktur umorganisiert, kann es passieren, dass man die Daten nicht mehr laden kann.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Tris hat geschrieben:Du musst binär speichern/öffnen mit pickle.
Kommt darauf an, welches Protocol man verwendet bzw. welchen protocol-Parameter man übergibt.
Aber es stimmt natürlich, dass man mit 'wb'/'rb' auf der sicheren Seite ist.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

mutetella hat geschrieben:
Tris hat geschrieben:Du musst binär speichern/öffnen mit pickle.
Kommt darauf an, welches Protocol man verwendet bzw. welchen protocol-Parameter man übergibt.
Alle davon sind binär auch wenn es nicht immer danach aussieht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@Leonidas
Weshalb kann ich dann via protocol 0 gepickelte Daten im 'non-binären' Modus speichern und lesen?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

mutetella hat geschrieben:Weshalb kann ich dann via protocol 0 gepickelte Daten im 'non-binären' Modus speichern und lesen?
Weil es zulässig ist.

"Be sure to always open pickle files created with protocols >= 1 in binary mode. For the old ASCII-based pickle protocol 0 you can use either text mode or binary mode as long as you stay consistent."
Benutzeravatar
snafu
User
Beiträge: 6897
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Zum Abspeichern von Spielständen und dergleichen würde ich ja eher XML oder (bevor ich erschlagen werde) JSON verwenden. Pickle ist IMHO nur zum temporären Zwischenspeichern wirklich geeignet. Anwendungsfälle wären zum Beispiel die Kommunikation zwischen zwei verschiedenen Python-Interpreter Prozessen oder in bestimmten Situationen zwecks Caching. In deinem Fall solltest du aber wie gesagt besser ein eigenes Datenformat erstellen. Denkbar wären zweistufige Dictionaries ("Kategorien" auf der obersten Ebene und Eigenschaften mit Werten jeweils als Inhalt der Untergruppe), welche im schon oben genannten JSON-Format abgespeichert werden. Das ist auf Dauer einfach robuster.

Hier mal ein Beispiel, wie so eine JSON-Datei aussehen kann: http://de.wikipedia.org/wiki/JSON#Beispiel
BlackJack

@mutetella: Wenn Du das konsequent und auf dem selben Betriebssystem falsch machst, dann begehst Du den gleichen Fehler beim Schreiben und beim Lesen. Das funktioniert mit *jedem* Pickle-Protokoll. Was mit *keinem* funktioniert, auch nicht mit 0, ist das Mischen von 'b' und nicht 'b' beim Lesen/Schreiben, und das Lesen von Pickles die unter Windows ohne 'b' gespeichert wurden unter einem anderen System — egal ob mit oder ohne 'b'.

@/me: Mein letzter Satz eben widerspricht anscheinend der Dokumentation, aber das ist die Erfahrung die ich mit Pickles gemacht habe.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:@/me: Mein letzter Satz eben widerspricht anscheinend der Dokumentation, aber das ist die Erfahrung die ich mit Pickles gemacht habe.
Der Punkt ist, dass man sich das picklen im Textmodus gar nicht erst angewöhnen sollte. Es geht halt nur mit dem Protokoll-Level 0 und sonst nicht. Der Binärmodus hingegen funktioniert immer.

Auf das grundsätzliche Pickle-Problem bin ich schon sehr früh gestoßen. Ich hatte eine komplexe XML-Datei die transformiert und in diverse aus eigenen Klassen aufgebaute Python-Datenstrukturen übernommen wurde. Das passierte bei jedem Programmstart. Zur Performancesteigerung war dann das picklen der Daten und ein gepickletes Einlesen gut geeignet. Dann kam der Tag als ich die Klassen umbaute und mir das ganze Zeug beim Einlesen um die Ohren flog. Selten war ich so glücklich über eine Versionskontrollsystem ...
Benutzeravatar
vegaseat
User
Beiträge: 6
Registriert: Montag 28. Januar 2013, 22:53
Wohnort: Las Vegas Nevada USA

Ach du lieber Himmel!
Du kannst nur die Klasseninstanz pickeln. Die genaue Klasse muss in deinem Program vorhanden sein.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

/me hat geschrieben:Be sure to always open pickle files created with protocols >= 1 in binary mode. For the old ASCII-based pickle protocol 0 you can use either text mode or binary mode as long as you stay consistent.
Als ich die Dokumentation gelesen habe, stand das dort noch nicht... ich schwör's...! :mrgreen:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

mutetella hat geschrieben:Als ich die Dokumentation gelesen habe, stand das dort noch nicht... ich schwör's...! :mrgreen:
Du kennst doch den alten Journalisten-Spruch: "Aber schreib das erst in Wikipedia damit es auch stimmt.". :D
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

vegaseat hat geschrieben: Du kannst nur die Klasseninstanz pickeln.
Du meinst ein "Exemplar" :P
vegaseat hat geschrieben: Die genaue Klasse muss in deinem Program vorhanden sein.
Und die "ungenaue" muss wo stehen? :twisted:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten