Seite 2 von 4
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 10:52
von Xfd7887a
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?
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 10:56
von EyDu
Xfd7887a hat geschrieben:Welcher Fehler ist das?
Nimm das except mal raus

Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 11:02
von 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.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 11:33
von Xfd7887a
Ok, danke. Werde mich damit auseinandersetzen

Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 12:09
von Xfd7887a
Die Ausgabe ist:
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.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 12:16
von 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.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 12:44
von Xfd7887a
Danke

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

Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 12:57
von 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`?
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 13:03
von Xfd7887a
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.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 13:28
von mutetella
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
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 13:31
von Sirius3
Btw.: für pickle solltest Du die Dateien für binäres Lesen und Schreiben öffnen.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 13:33
von Xfd7887a
Habe ich auch gerade gesehen. Spielt für mich jetzt keine Rolle, aber gut, dass ich es für weitere Projekte weiß. Den anderen Punkt verstehe ich nicht, ich fange erst mit Klassen an

.
# Edit: Apropos Klassen: Würde es Sinn machen, mein Programm mit Klassen auszudrücken? Wenn ich irgendwann ne GUI einprogrammiere, werde ich sicherlich nicht drum 'rum kommen.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 13:43
von BlackJack
@mutetella: Ergänzend zu mutetella's Anmerkungen: `pickle` ist auf Python beschränkt. (Falls es doch eine Bibliothek für eine andere Programmiersprache geben sollte: JSON-Bibliotheken gibt es für *sehr* viele Programmiersprachen.) Man könnte zum Beispiel zur Anzeige der Aufgaben eine Webseite mit JavaScript schreiben, die diese Datei nachlädt und dann anzeigt. Die HTML-Datei braucht man dann nur einmal auf den Webserver hochladen und zum aktualisieren bräuchte man nur noch die JSON-Datei erneut hochladen.
Bei diesem Programm ist das mit dem ”menschenlesbar” vielleicht noch nicht so interessant, aber es kann manchmal zur Fehlersuche hilfreich sein wenn man sich das gespeicherte Ergebnis ausserhalb der eigenen Anwendung anschauen kann.
Ich nutze `pickle` nur noch für kurzfristig gespeicherte Daten, zum Beispiel für Caches, oder zum serialisieren von Daten für die Übertragung zu anderen Python-Programmen. Oft auch indirekt weil entsprechende Bibliotheken das halt nutzen.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 13:53
von mutetella
Xfd7887a hat geschrieben:Den anderen Punkt verstehe ich nicht, ich fange erst mit Klassen an.
Das heißt, dass Du zwischen Speichern und Laden von Klassenexemplaren nichts an einer Klasse ändern darfst. Wenn Du also aus irgendeinem Grund der Klasse noch zusätzliche Attribute hinzufügst oder bestehende wegnimmst, kannst Du mit den bereits gepickelten Daten erstmal nichts mehr anfangen, da diese in die geänderte Klassenstruktur nicht mehr hineinpassen, da sie ja von den geänderten Attributen nichts wissen. In einem solchen Fall muss man also die alten Daten erstmal in die alte Klassenstruktur laden, diese Exemplare dann in die neue Klassenstruktur konvertieren und dann erst wieder abspeichern. Sehr mühsam und eigentlich unnötig, wenn man auf pickle im Produktiveinsatz verzichtet, da es ja eben ausreichend Ersatz gibt, z. B. eben json oder gleich 'ne Datenbanklösung, wenn das denn nötig ist.
mutetella
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 13:56
von Xfd7887a
Ok, das habe ich verstanden. Also ist json im Allgemeinen die bessere Wahl.
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 14:19
von mutetella
Xfd7887a hat geschrieben:Apropos Klassen: Würde es Sinn machen, mein Programm mit Klassen auszudrücken?
Ich finde ja. Momentan befinden sich Deine Daten `aufgaben` auf Modulebene, wo Sie eigentlich nicht hingehören. Wenn Du dafür eine Klasse `Tasks` (ich bevorzuge ja englische Namen) erstellst fände ich das übersichtlicher. Zudem wäre dann zusammen, was zusammengehört: Die Attribute einer Aufgabe wie Fach, Datum etc. und die Methoden (Funktionen), die Du darauf anwendest. Zum Beispiel:
Code: Alles auswählen
class Task(object):
def __init__(self, subject, date, theme, grade):
self.subject = subject
self.date = date
self.theme = theme
self.grade = grade
def __str__(self):
return 'Task: {s} {d} {t} {g}'.format(
s=self.subject, d=self.date,
t=self.theme, g=self.grade)
class Tasks(object):
def __init__(self):
self.tasks = set()
def add_task(self, task):
self.tasks.add(task)
def __iter__(self):
for task in self.tasks:
yield task
Code: Alles auswählen
>>> import todo
>>> tasks = todo.Tasks()
>>> tasks.add_task(todo.Task('Mathe', '28.06.2014', 'Bruchrechnen', 'befriedigend'))
>>> tasks.add_task(todo.Task('Deutsch', '27.06.2014', 'Rechdschraibuhnk', 'ungenuegend'))
>>> for task in tasks:
... print task
...
Task: Mathe 28.06.2014 Bruchrechnen befriedigend
Task: Deutsch 27.06.2014 Rechdschraibuhnk ungenuegend
Das soll jetzt nur mal den Einsatz von Klassen demonstrieren und muss jetzt nicht zwingend für das, was Du vorhast 1:1 passen...
mutetella
Re: Aufgabenverwaltung
Verfasst: Samstag 28. Juni 2014, 14:23
von Xfd7887a
Ok, dann werde ich das demnächst mit Klassen probieren. Danke.
Re: Aufgabenverwaltung
Verfasst: Sonntag 29. Juni 2014, 11:46
von Xfd7887a
Ich glaube, ich werde mich erstmal gründlicher in die OOP einarbeiten. Das ist doch komplizierter als ich dachte und ich weil mein Programm nicht "verschlimmbessern".
Re: Aufgabenverwaltung
Verfasst: Sonntag 29. Juni 2014, 11:52
von snafu
@mutetella: Das was du "theme" nennst, würde man AFAIK eher als "topic" bezeichnen. Wobei laut Online-Wörterbuch "theme" genau so gut passen würde. Für mich klingt es in dem Zusammenhang jedenfalls besser, "topic" zu sagen.
Re: Aufgabenverwaltung
Verfasst: Sonntag 29. Juni 2014, 12:05
von snafu
Xfd7887a hat geschrieben:Ich glaube, ich werde mich erstmal gründlicher in die OOP einarbeiten. Das ist doch komplizierter als ich dachte und ich weil mein Programm nicht "verschlimmbessern".
OOP selbst ist relativ leicht zu verstehen. Insbesondere dann, wenn man Vererbung erstmal außen vorlässt. Es wird eigentlich erst dann wirklich komplex, wenn man die besagte Vererbung nutzt und wenn man die Funktionalität auf Basis bestimmter Protokolle aufbaut. Im hier gezeigten Beispiel wurde das Protokoll für Iteratoren mittels ``__iter__`` implementiert. Häufig findet man auch Implementationen von ``__str__`` oder ``__repr__``. Das sieht anfangs wie Voodoo aus (ist es ja eigentlich auch ^^), aber mit der Zeit gewöhnt man sich daran und beginnt, die entsprechenden Vorteile zu erkennen und sinnvoll zu nutzen. Ob man die Klasse ``Tasks`` in seiner vorgeschlagenen Form wirklich so benötigt oder ob man nicht direkt ein Set (also ohne die "Hülle") benutzen möchte, sei übrigens mal dahingestellt...