Zum Inhalt springen

Aufgabe 17 - Notenverwaltung mit CSV und JSON

Zu Zen-Modus wechseln

Daten überleben das Programmende: Sie lesen Prüfungsdaten aus einer CSV-Datei, verarbeiten sie objektorientiert, werten sie aus und exportieren die Ergebnisse als JSON, mit sauberer Fehlerbehandlung für alles, was an der Datengrenze schiefgehen kann (siehe Kapitel Dateien und Datenformate). Die ausgeteilte Datei enthält absichtlich fehlerhafte Zeilen; der professionelle Umgang damit ist der Kern der Übung.

  • Kapitel Dateien und Datenformate vollständig; Kapitel Exceptions (eigene Exception-Klassen).
  • Die Datei grades.csv: Spalten name;subject;grade;date, Trennzeichen Semikolon, 60 Datenzeilen, darunter drei absichtlich fehlerhafte (eine Note als Wort, ein kaputtes Datum, eine Zeile mit fehlender Spalte). Korrekt eingelesen ergibt das 57 exams loaded, 3 lines skipped.
  • Sie lesen und schreiben CSV- und JSON-Dateien mit den Standardmodulen, inklusive Encoding und Trennzeichen.
  • Sie übersetzen zwischen Rohdaten, Objekten und Austauschformaten (to_dict/from_dict).
  • Sie behandeln Datei- und Formatfehler mit Exceptions, ohne Fehler zu verschweigen.
  • Reproduktion: Dateien öffnen, Inhalte ausgeben, das Zeilenformat beschreiben (Teil A).
  • Reorganisation und Transfer: Rohdaten in Objekte überführen, Auswertungen entwickeln, Ergebnisse exportieren (Teile B und C).
  • Reflexion, Problemlösung und Urteilsbildung: Fehlerstrategien entwerfen, Formatverträge definieren und die Robustheit des eigenen Programms nachweisen (Teil D).

Die Übung ist auf etwa zwei Stunden ausgelegt. Teil D ist der Expertenteil.

  1. Öffnen Sie grades.csv zuerst im Editor: Welches Trennzeichen, welche Spalten, welche Kopfzeile? Notieren Sie den “Vertrag” der Datei in zwei Zeilen Kommentar.
  2. Lesen Sie die Datei mit csv.DictReader (Achtung: delimiter=";", encoding="utf-8", newline="") ein und geben Sie die ersten fünf Zeilen als Dictionaries aus.
  3. Welchen Typ hat der Notenwert nach dem Einlesen? Belegen Sie die Antwort mit type().
  1. Implementieren Sie die Klasse Exam mit name, subject, grade (int, 1 bis 5) und date, plus __str__ und to_dict().
  2. Definieren Sie DataError(Exception). Implementieren Sie load_exams(path): liefert eine Liste von Exam-Objekten. Fehlerhafte Zeilen werden übersprungen, aber mit Zeilennummer und Grund in einer Fehlerliste gesammelt und zurückgegeben, nicht verschwiegen. Eine fehlende Datei führt zu DataError mit verständlicher Meldung.
  3. Ausgabe nach dem Laden: 57 exams loaded, 3 lines skipped plus die Details der übersprungenen Zeilen. Finden Sie alle drei präparierten Fehler?
  1. Berechnen Sie: Notenschnitt je Fach, Notenschnitt je Person, bestes Fach der Klasse.
  2. “Gefährdet”: alle Personen mit einem Schnitt schlechter als 4.0 in mindestens einem Fach.
  3. Implementieren Sie save_report(path, ...): schreibt die gesamte Auswertung als verschachteltes JSON (indent=2, ensure_ascii=False); Struktur etwa: Fächer mit Statistik, Personen mit Schnitten, Liste der Gefährdeten.
  4. Schließen Sie den Kreis: Lesen Sie das eigene JSON wieder ein und prüfen Sie zwei Stichprobenwerte mit assert gegen die Originalberechnung.

Teil D - Expertenteil: Der Datenlieferant ist unzuverlässig

Abschnitt betitelt „Teil D - Expertenteil: Der Datenlieferant ist unzuverlässig“
  1. Machen Sie load_exams trennzeichentolerant: Die Funktion erkennt selbstständig, ob eine Datei Komma oder Semikolon verwendet (Ansatz: erste Zeile lesen und zählen, oder csv.Sniffer recherchieren). Testen Sie mit einer selbst erzeugten Komma-Variante der Datei.
  2. Verschärfen Sie die Validierung pro Zeile: Note muss 1 bis 5 sein, das Datum muss dem Format JJJJ-MM-TT entsprechen (Regex oder datetime.date.fromisoformat mit Exception-Behandlung), kein Feld darf leer sein. Jede Verletzung landet mit präzisem Grund in der Fehlerliste.
  3. Fehlerprotokoll für den Datenlieferanten: Schreiben Sie die gesammelten Fehlerzeilen in eine eigene Datei errors.csv (Spalten line;content;reason, Semikolon, encoding="utf-8"). Jede übersprungene Zeile wird so zu einem korrigierbaren Eintrag statt einer stillen Lücke: Zeilennummer, ursprünglicher Rohinhalt und der genaue Grund der Ablehnung. Prüfen Sie selbst zwei Fälle: Bei der ausgeteilten grades.csv muss die Protokolldatei genau die drei bekannten Fehler enthalten; bei einer selbst erzeugten, fehlerfreien Datei nur die Kopfzeile.
  4. Beurteilen Sie in drei Sätzen: Warum ist “fehlerhafte Zeilen still verwerfen” bei einer Notenliste nicht bloß schlechter Stil, sondern ein inhaltliches Risiko? Wer muss von den drei übersprungenen Zeilen erfahren?
  1. Warum gehört zu jedem open() für Textdateien encoding="utf-8"?
  2. Warum liefert CSV grundsätzlich Strings, und wo im Programm gehört die Umwandlung hin?
  3. Welche drei Fehlerklassen muss ein Programm behandeln, das fremde Dateien einliest?
  4. Wann wählen Sie CSV, wann JSON? Je ein Kriterium genügt.
  5. Was leistet die Rundreise (schreiben, wieder einlesen, vergleichen) als Testtechnik?

grades.py (Klasse, Laden, Auswertung, Export), das erzeugte report.json und die errors.csv aus Teil D sowie ein kurzes Protokoll: Welche drei fehlerhaften Zeilen wurden gefunden und mit welcher Begründung? Committet im Git-Repository.