EOFerror bei Pickel

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
Benutzeravatar
jtschoch
User
Beiträge: 400
Registriert: Freitag 6. Mai 2011, 15:40
Kontaktdaten:

Hallo Pythoner,

Ich habe schon wieder mal ein Problem!
Ich habe mir ein Consolenspiel gemacht,
da wollte ich eine Save funktion mit Pickle gemacht.
Aber dort kam eine Fehlermeldung,
ich habe das ganze nochmal in ein extra-file geschrieben,
aber nur die Save funktion ... und das selbe.
Ich habe schon gegoogleld,
und da steht das das ein Fehler von Python ist,
und tritt auf wenn man raw- oder input verwendet.

Zur Fehlerbehandlung habe ich noch nicht's richtiges gefunden auser das: http://abop-german.berlios.de/read/try-except.html
Aber das ist ein Bischen unpraktisch.

Kann mir jemand Helfen wie ich das gut lösen könnte?

Code: Alles auswählen

import random, pickle
zins_werte = [1.5, 2.0, 2.5, 3.0]
########~Werte~########

#~Bank und Geld
bargeld = 100
neue_zinsen = random.choice(zins_werte)
zinsen = float(neue_zinsen)
bank = 0
tag = 0

#~Nahrung

brot = 1.5
wasser = 1.0
#~Nahrung-Preise

wasser_preis = 0.8
brot_preis = 0.5
#~Funktionen
trinken = 100
essen = 100


#~Extra
bankkonto = bank
ereignisse = 10

op = input("Load(1) or Save(2)?\n")
if op == 1:
	op = None
	load = open("save.txt", 'r')
	bargeld, zinsen, bank, tag, brot, wasser, wasser_preis, brot_preis, trinken, essen, ereignisse = pickle.load(load)
if op == 2:
	f = open("save.txt", 'w')
	pickle.dump([bargeld, zinsen, bank, tag, brot, wasser, wasser_preis, brot_preis, trinken, essen, ereignisse], f)	

Code: Alles auswählen

jtschoch@triebisch:~/Prog/python/Spiel$ python test_save.py
Load(1) or Save(2)?
1
Traceback (most recent call last):
  File "test_save.py", line 33, in <module>
    bargeld, zinsen, bank, tag, brot, wasser, wasser_preis, brot_preis, trinken, essen, ereignisse = pickle.load(load)
  File "/usr/lib/python2.7/pickle.py", line 1378, in load
    return Unpickler(file).load()
  File "/usr/lib/python2.7/pickle.py", line 858, in load
    dispatch[key](self)
  File "/usr/lib/python2.7/pickle.py", line 880, in load_eof
    raise EOFError
EOFError
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

jtschoch hat geschrieben:Ich habe mir ein Consolenspiel gemacht,
da wollte ich eine Save funktion mit Pickle gemacht.
Aber dort kam eine Fehlermeldung,
ich habe das ganze nochmal in ein extra-file geschrieben,
aber nur die Save funktion ... und das selbe.
Ich habe schon gegoogleld,
und da steht das das ein Fehler von Python ist,
und tritt auf wenn man raw- oder input verwendet.
Lerne Fehler richtig zu interpretieren.

Der Fehler den du zeigst tritt beim Laden auf, nicht beim Speichern. Ein Zusammenhang mit (raw-)input existiert garantiert nicht. Du hast entweder das Gelesene nicht korrekt verstanden oder dort hat auch jemand überhaupt keine Ahnung gehabt. Der Link zu diesem Hinweis interessiert mich jetzt wirklich.

Auf Anhieb sehe ich drei Probleme. Du schreibst eine Liste in die Datei und versuchst ein Tupel zu lesen, du öffnest die Datei nicht im Binärmodus und du schließt die Datei auch nicht wieder. Letzteres würde dir nicht passieren, wenn du die Datei mit dem Konstrukt

Code: Alles auswählen

with open(filename) as fp:
    # do something
öffnen würdest. open stellt beim Aufruf mit with sicher, dass die Datei nach dem Ende des Blocks garantiert geschlossen ist.

Von input solltest du übrigens bei Python 2.x die Finger lassen und stattdessen raw_input verwenden. input akzeptiert jeglichen Python-Code und damit reißt du dir eine riesige Sicherheitslücke ins Programm.
Benutzeravatar
jtschoch
User
Beiträge: 400
Registriert: Freitag 6. Mai 2011, 15:40
Kontaktdaten:

Sorry, habe mich verschrieben
und auserdem ist das Pickele das ist für Listen gedacht!

Hier das ganze Game:
http://www.python-forum.de/pastebin.php?mode=view&s=250 die Funktioniert hier nicht richtig ich habe bei mir bar änderrungen übernommmen

Vielen Dank funktioniert!
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

jtschoch hat geschrieben:und auserdem ist das Pickele das ist für Listen gedacht!
Was willst du mir jetzt damit sagen? "Pickle ist die geeignete Methode um eine Liste in ein Tupel zu verwandeln."?
Du öffnest die Datei immer noch nicht im Binärmodus und du schließt sie nach dem Speichern nicht. Es ist durchaus möglich, dass das Programm aktuell trotzdem wie gewünscht arbeitet, aber das kann nach der nächsten Programmänderung oder mit einer anderen Laufzeitumgebung schon vorbei sein.
Benutzeravatar
jtschoch
User
Beiträge: 400
Registriert: Freitag 6. Mai 2011, 15:40
Kontaktdaten:

Hier sind die Änderrungen.
Aber ich habe noch eine Frage,
wie kann ich das machen das es die geladenen werte durch die Alten ersetzt?
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
BlackJack

@jtschoch: Da besteht aber noch *viel* Verbesserungsbedarf.

Von der Form her ist zu weit eingerückt. Per Konvention verwendet man vier Leerzeichen pro Ebene und nicht acht. Dann sind vielleicht auch einige Zeilen, die jetzt zu lang sind, auch unter 80 Zeichen ohne dass man sie umbrechen muss.

Der Umweg über `neue_zinsen` ist überflüssig, genau wie das umwandeln einer Gleitkommazahl in eine Gleitkommazahl.

Du bist eigentlich schon lange genug dabei um Funktionen kennengelernt zu haben. Alles auf Modulebene was keine Konstanten sind, sollte in Funktionen verschwinden. Mehrzahl wohlgemerkt, denn das ist deutlich zu viel Komplexität und zu viele Namen für *eine* Funktion. Da sind 153 Anweisungen in 33 Verzweigungen und es werden 31 verschiedene Namen verwendet. Das ist zu viel um den Überblick zu behalten.

Ausführlich getestet hast Du es anscheinend nicht, sonst wäre aufgefallen, dass der Name `zahlung`, der in in Zeile 123 verwendet wird, nirgends an einen Wert gebunden wurde.

Deine Bank funktioniert nicht konsistent weil Du die Namen `bank` und `bankkonto` verwendest. `bank` ist aber immer an 0 gebunden weil im Programm `bankkonto` manipuliert, aber `bank` beim speichern und laden des Spielstands verwendet wird.

Einige Namen sind auch schlecht gewählt. Zum Beispiel `bank`. Da würde man ein Objekt erwarten, welches eine Bank repräsentiert. Und bei `brot` und `wasser` kommt man auch nicht darauf dass diese Namen so etwas wie den *Nährwert* von diesen beiden Nahrungsmitteln repräsentieren soll. `zinsen` sollte eher `zinssatz` heissen.

Der Name `ereignisse` ist ein wenig zu allgemein, da es nur verbrauchte Arbeitsstunden erfasst. Ausserdem glaube ich nicht, dass das zuverlässig funktioniert was Du da machst, denn den Wert sollte der Anwender nicht unter 0 bekommen können. Und wenn er negativ ist, kann man auch 10 Stunden arbeiten gehen. Und zwar wiederholt.

Bei den Waren die Namen und Preise auf verschiedene Bezeichner zu verteilen ist unübersichtlich. Wenn Daten zusammen gehören, sollte man sie auch in *einer* Datenstruktur speichern. Und wenn man verschiedene gleichartige Datenstrukturen hat, sollte man diese auch wieder zu einer Datenstruktur zusammen fassen, und nicht an verschiedene Namen binden. Bei der Programmkomplexität bieten sich dafür IMHO schon eigene Klassen an. Man sollte aber mindestens Wörterbücher verwenden. Schau Dir einfach mal den Aufwand an, den man betreiben muss, wenn man Dein Programm um sagen wir mal Hamburger und Bier erweitern möchte. Dafür sollte man nur an *einer* Stelle im Programm eine Datenstruktur erweitern müssen und nicht wie bei Dir im ganzen Programm suchen müssen wo die Namen `wasser` und `brot` auftauchen um dort das Programm durch Code zu erweitern.

An den Namen `liste` bindest Du eine Zeichenkette. Sehr verwirrend.

Die Haupt-``while``-Schleife hat einen ``else``-Zweig, enthält aber gar kein ``break``. Damit ist das ``else`` überflüssig und man könnte den Inhalt davon einfach hinter die Schliefe schreiben. Das ``print False`` erscheint mir aber sowieso etwas sinnfrei!?

Bei der Bank kann man nur einzahlen, aber nichts abheben!? Da würde ich kein Konto eröffnen. ;-)

Beim Zweig für das Einkaufen ist Programmieren durch kopieren und einfügen verwendet worden. Solche Wiederholungen sollte man vermeiden, denn wenn man etwas ändern will, muss man immer daran denken die Änderung an allen Kopien vorzunehmen. Genau hier ist ja dann auch der Fehler mit `zahlung` passiert. Ausserdem kommen hier auch redundante Daten vor. Wenn man die Preise ändern will, muss man das an zwei weit auseinander liegenden Stellen, in verschiedenen Formen, aber zueinander passend tun. Das ist eine unnötige Fehlerquelle.

Ein ``else: None`` ist überflüssig.

Beim Laden verwendest Du ``with`` beim Speichern aber nicht!? Ausserdem schliesst Du nach dem Speichern die Datei immer noch nicht. Einfach nur ``f.close`` hat keinen Effekt — Du musst die Methode auch *aufrufen*. Oder eben ``with`` verwenden.
Benutzeravatar
jtschoch
User
Beiträge: 400
Registriert: Freitag 6. Mai 2011, 15:40
Kontaktdaten:

Ich wusste schon das noch viel verbesserrungsbedaf ist das ist nur der grobe teil.
Deshalb auch die ausgabe False bei else, das war nur zum test.
Es ging mir mehr um die Funktionen und Save/Load.
Aber bei vielen dingen muss ich erst nachdenken bzw. in hier nachfragen,
und auserdem habe ich das Programm erst gestern geschrieben.
Und wegen den 8 Zeichen, ich habe es unter ubuntu in gedit geschrieben!

Es wäre aber mal nett mir mal einen Vorschlag, wie ich das machen könnte zu geben z.B. beim Supermarkt u. Seichern/Laden

Aber trotzdem danke das du mir So *viele* Anhaltspunkte gegeben hast,
die ich Falsch gemacht habe!

Habe das mit dem Abhenben/Auszahlen verbessert und
bei else statt None "Du bist gestorben" hingeschrieben.

Neue: [url]http://www.python-forum.de/pastebin.php ... &s=253/url] jetzt dürften die funktionen auch besser funktionieren,
vorallem Arbeitem
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
BlackJack

@jtschoch: So einen grossen groben Teil sollte es nicht geben. Ob Du das Programm gestern oder vor einer Woche geschrieben hast, sollte ebenfalls egal sein und ist keine wirkliche Erklärung für den grossen Verbesserungsbedarf. Man teilt das nicht erst auf Funktionen auf wenn man schon ein 200-Zeilen-Monstrum runter geschrieben hat, sondern schon deutlich vorher.

Unter welchem System und mit welchem Editor es geschrieben wurde, ist keine Erklärung für die verwendete Einrücktiefe. Die sollte vier Leerzeichen pro Ebene sein. Punkt. Bei jedem für Programmierung geeigneten Editor kann man das Einstellen. So auch bei ``gedit``.

Wofür genau brauchst Du jetzt einen Vorschlag?

Der letzte Absatz macht keinen Sinn!? Du bringst da glaube ich zwei verschiedene ``else``-Zweige durcheinander und man kann aus dem Satz nicht herauslesen was Du nun wo und wie geändert hast.
Benutzeravatar
jtschoch
User
Beiträge: 400
Registriert: Freitag 6. Mai 2011, 15:40
Kontaktdaten:

Ja, ich habe es jetzt eingestellt bei gedit,
ich habe es mal im idle ausgeführt und haufen Fehlermeldungen,
als ich die einrückgungen und Fehler kurigiert habe ging auch die Funktion von Abeiten man kann da jetzt auch 10 Stunden Arbeiten und
dann muss man schlafen gehen.

Und ich brauche noch Vorschläge zu dem was ich verbessern soll ich verstehe mansches nicht so richtig!
Das Laden Funktioniert nicht! Speichern schon.
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Benutzeravatar
jtschoch
User
Beiträge: 400
Registriert: Freitag 6. Mai 2011, 15:40
Kontaktdaten:

Hier die 1. Verbesserrung:
http://www.python-forum.de/pastebin.php?mode=view&s=254

Ich bräuchte erstmal Hilfe bei der load funktion.
Das mit dem Brot und Wasser ist dass so gemeint?
angebote = ["Brot", 1.0, "Wasser", 1.5]
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

jtschoch hat geschrieben:Das mit dem Brot und Wasser ist dass so gemeint?
angebote = ["Brot", 1.0, "Wasser", 1.5]
Eine Liste ist wohl eher nicht das Mittel der Wahl. Überleg doch mal, wie du dann auf die Daten zugreifen müsstest.

Eine Struktur mit einem bereits eingebauten Zugriff über Schlüssel ist da wohl eher angebracht.
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

/me hat geschrieben:Auf Anhieb sehe ich drei Probleme. Du schreibst eine Liste in die Datei und versuchst ein Tupel zu lesen
Hm, ich glaube, du täuschst dich. Du meinst wohl die Zeile

Code: Alles auswählen

bargeld, zinsen, bank, tag, brot, wasser, wasser_preis, brot_preis, trinken, essen, ereignisse = pickle.load(load)
pickle.load lädt aber immer das abgespeicherte Objekt, das war ja die Liste. Ein Tupel kommt überhaupt nicht vor (links vom Gleichheitszeichen steht eine target list), so dass ich da eigentlich kein Problem sehe.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

bords0 hat geschrieben:Ein Tupel kommt überhaupt nicht vor (links vom Gleichheitszeichen steht eine target list), so dass ich da eigentlich kein Problem sehe.
Du hast recht. Meine Interpretation entstand vermutlich aus einem gewissen Widerwillen gegen die Verwendung einer Liste beim Speichern.
Antworten