Aufgabenverwaltung

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.
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Habe das ganze so geändert:

Code: Alles auswählen

try:
    with open("aufgaben.txt") as aufgaben_datei:
        AUFGABEN = load(aufgaben_datei)
except:
    with open("aufgaben.txt", "w") as aufgaben_datei:
        dump(dict(), aufgaben_datei)
        AUFGABEN = load(aufgaben_datei)
Wird nun die Datei automatisch geschlossen?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Das ist eine komische Logik... ich musste da erst genau hinsehen, um zu begreifen, dass Du die Datei "leer" anlegst, wenn diese nicht geöffnet werden konnte.

Lesen und Schreiben würde ich komplett trennen, also eine Funktion ``dump`` und eine ``load`` oder so ähnlich.

Wenn Die Datei (noch) nicht existiert, dann gib einfach ein *leeres* Dictionary zurück :-)

Das ist imho das sinnvollere Vorgehen!

Und fange niemals *alle* Exceptions ab, sondern nur die, auf die Du reagieren willst. In Deinem Falle also eine ``FileNotFoundError``-Exception.

Ansonsten: Ja, so werden die Dateien automatisch geschlossen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Danke :D
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Hyperion hat geschrieben:Und fange niemals *alle* Exceptions ab, sondern nur die, auf die Du reagieren willst. In Deinem Falle also eine ``FileNotFoundError``-Exception.
Genau das. Spiel mal durch was passiert, wenn du keine Spreibrechte fuer die Datei "aufgaben.txt" hast :)
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Ich habe gerade versucht mein Programm zu "verbessern". Leider habe ich rumgemurkst, jetzt werden Änderungen einfach nicht gespeichert. Hier das Script: https://github.com/toxinman/stuff/blob/master/todo.py Ich weiß nicht, was ich geändert habe.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich gebe mal einen Tipp ab: Du beendest das Programm über die "programm_beenden"-Funktion. Diese ruft dann allerdings die exit-Funktion auf, welche das Programm direkt beendet. Dadurch wird das Speichern nicht mehr ausgeführt. Bei solchen Problemen hilft es oft, wenn du ein paar print-Statements in dein Programm einbaust. Dann siehst du recht schnell ob du irgendwo im Code ankommst oder nicht.
Das Leben ist wie ein Tennisball.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

cofi hat geschrieben:[...] keine Spreibrechte fuer die Datei [...]
Muss es nicht Speibrechte[*] heißen?

[*]Von Bairisch: speiben (schbaim): spucken, erbrechen.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

@pillmuncher: Dann ist immer noch ein "b" zu viel 8)
Nein, das ist ein reichlich verungluecktes "Schreibrechte" :roll:
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Ich habe versucht, die Schleife explizit zu verlassen, aber die Datei wird immer noch nicht gespeichert :K
BlackJack

@Xfd7887a: Wie stellst Du das denn fest? Hast Du nach Programmende tatsächlich mal in die Datei geschaut, oder denkst Du das nur weil nach einem erneuten Programmstart keine Daten in `AUFGABEN` sind?

Hier sieht man schön warum nackte ``except``\s ohne konkrete Ausnahmen keine gute Idee sind. Du rennst wegen einem Programmierfehler immer in das ``except`` in Zeile 103 und merkst das nicht, weil dort eben nicht nur die Ausnahmensituationen behandelt werden die Du erwartest, sondern auch mindestens eine die bei einem korrekten Programm gar nicht vorkommen dürfte. Und der Fehler sorgt auch dafür das die Datei bei jedem Programmstart geleert wird.

Die Schreibweise von `AUFGABEN` ist für eine Datenstruktur die während des Programmlaufs verändert werden soll übrigens falsch. Ausschliesslich Grossbuchstaben werden per Konvention nur für konstante Werte verwendet.

Es wäre übrigens praktischer wenn Du beim Verlinken Deines Quelltextes nicht immer wieder das Master-Tag verwenden würdest, sondern einen Link auf die konkrete Revision die gemeint ist. Denn sonst kann man nach Änderungen an Master die Antworten hier nicht mehr wirklich nachvollziehen, sondern muss sich erst anhand des Beitragsdatums die richtige Revision auf Github heraus suchen.
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Ich glaube, ich habe nicht verstanden, was du meinst. Meine Änderung:

Code: Alles auswählen

 with open("aufgaben.txt", "w") as aufgaben_datei:
      try:
 -        AUFGABEN = load(aufgaben_datei)
 -    except:
 -        AUFGABEN = dict()
 +        aufgaben = load(aufgaben_datei)
 +    except IOError:
 +        aufgaben = dict()
Leider funktioniert es immer noch nicht, obwohl ich doch eigentlich nur abfange, wenn die Datei leer ist.
Hier sieht man schön warum nackte ``except``\s ohne konkrete Ausnahmen keine gute Idee sind. Du rennst wegen einem Programmierfehler immer in das ``except``
Welcher Fehler ist das?
Es wäre übrigens praktischer wenn Du beim Verlinken Deines Quelltextes nicht immer wieder das Master-Tag verwenden würdest, sondern einen Link auf die konkrete Revision die gemeint ist.
Wie geht das?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Xfd7887a hat geschrieben:Welcher Fehler ist das?
Nimm das except mal raus ;-)
Das Leben ist wie ein Tennisball.
BlackJack

@Xfd7887a: Die Änderung behandelt jetzt alles was ein `IOError` ist, das ist mehr als nur das die Datei nicht existiert. Der Fall das die Datei nicht existiert, kann nebenbei gesagt innerhalb des ``try``/``except`` überhaupt gar nicht auftreten weil Du dort bereits ein geöffnetes Dateiobjekt vor dem betreten hast. Dann *muss* die Datei existieren, denn wie könnte man sonst so ein Objekt haben!?

Gib der Ausnahme in dem ``except`` noch einen Namen und gib das Ausnahmeobjekt dann doch einfach mal mit ``print`` aus, dann siehst Du ja was die Nachricht von dem Objekt sagt.

Zum verlinken: Du könntest zum Beispiel über die History gehen und da beim gewünschten Commit-Stand auf „Browse code →” klicken um zum Stand der Datei zu dem konkreten Commit zu kommen. So bin ich auf den Link in meinem letzten Beitrag gekommen.
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Ok, danke. Werde mich damit auseinandersetzen :D
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Die Ausgabe ist:

Code: Alles auswählen

File not open for reading
Das verstehe ich nicht, ich habe die Datei doch geöffnet.
Der Fall das die Datei nicht existiert, kann nebenbei gesagt innerhalb des ``try``/``except`` überhaupt gar nicht auftreten weil Du dort bereits ein geöffnetes Dateiobjekt vor dem betreten hast.
Ja, die Datei ist immer da. Mir geht's im Moment darum, ob sie gefüllt oder leer ist.
BlackJack

@Xfd7887a: Da steht nicht die Datei wäre nicht geöffnet sondern sie ist nicht *zum lesen* geöffnet. Man kann aus einer Datei die man zum schreiben öffnet, nicht lesen. Und wenn man eine zum schreiben öffnet, wird sie geleert — das heisst was Du ganz am Anfang machst, ist die Daten zu löschen die Du eigentlich einlesen möchtest.
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Danke :D
Habe das jetzt so:

Code: Alles auswählen

def datei_laden():
    datei = open("aufgaben.txt")
    aufgaben = pickle.load(datei)
    return aufgaben


def in_datei_schreiben(daten):
    datei = open("aufgaben.txt", "w")
    pickle.dump(daten, datei)
    datei.close()
und so:

Code: Alles auswählen

try:
    aufgaben = datei_laden()
except IOError:
    in_datei_schreiben(dict())
    aufgaben = datei_laden()
gelöst. Sicherlich ist das ziemlich umständlich, aber es funktioniert :D
BlackJack

@Xfd7887a: Da wird beim Laden die Datei wieder nicht geschlossen. Warum verwendest Du in den beiden Funktionen nicht die ``with``-Anweisung?

Und warum jetzt `pickle` statt `json`?
Xfd7887a
User
Beiträge: 135
Registriert: Montag 23. Juni 2014, 17:11

Stimmt, das habe ich übersehen:

Code: Alles auswählen

def datei_laden():
    with open("aufgaben.txt") as datei:
        aufgaben = pickle.load(datei)
    return aufgaben


def in_datei_schreiben(daten):
    with open("aufgaben.txt", "w") as datei:
        pickle.dump(daten, datei)
Weil das die bevorzugte Variante für Python zu sein scheint. Aber eigentlich ist das Format ja egal.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Xfd7887a hat geschrieben:Weil das die bevorzugte Variante für Python zu sein scheint.
Wäre ja mal interessant, was "die bevorzugte" Variante wirklich ist, aber Pickle IMHO nicht.
Xfd7887a hat geschrieben:Aber eigentlich ist das Format ja egal.
Also pickle hat für mich zwei entscheidende Nachteile: Zum einen sind pickle-Dateien nicht menschenlesbar, zum anderen darf sich, wenn Du pickle zum Speichern von Klassenexemplaren verwendest, an deren Struktur nichts ändern. Ok, letzteres betrifft Dich nicht, wollte ich aber erwähnt haben.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten