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

Arbeite gerade an weiteren Verbesserungen, nur leider verstehe ich nicht, was du mit
Das die Dateien nicht wieder geschlossen werden würde ich als Programmfehler ansehen. Man verlässt sich da auf Implementierungsdetails und Dateihandles sind eine limitierte Systemressource.
meinst. Wie soll ich die Datei schließen?
BlackJack

@Xfd7887a: Dateiobjekte haben eine `close()`-Methode dafür. Oder man verwendet das `open()` zusammen mit der ``with``-Anweisung.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Xfd7887a hat geschrieben:Wie soll ich die Datei schließen?
So:

Code: Alles auswählen

# Nutze die ``close``-methode auf File-Objekten:
file_object.close()
Besser, weil mit Absicherung gegen Ausnahmen während des Ablaufs, ist aber folgendes:

Code: Alles auswählen

with open(...) as file_object:
    # hantiere hier mit dem Objekt, rufe *nicht* ``close`` auf!
# das passiert nach Verlassen des Blocks automatisch :-)
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

Ok, danke. Wenn ich nun aber versuche, die Datei zu schließen, kommt folgende Meldung:

Code: Alles auswählen

AttributeError: 'dict' object has no attribute 'close'.
Das ist sicherlich logisch, da ich den Inhalt der Datei unter der Variablen "AUFGABEN" gespeichert habe.

Wie komme ich jetzt an die eigentliche Datei ran?
BlackJack

@Xfd7887a: Du musst diese Methode auf dem *Dateiobjekt* aufrufen, und nicht auf dem Wörterbuch mit den Aufgaben. Dazu musst Du dieses Dateiobjekt an einen Namen binden. Besser wäre aber das mit der ``with``-Anweisung zu machen.
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.
Antworten