9.2 CSV und JSON

Video

Dieses Short-Video wird zu einem späteren Zeitpunkt bereitgestellt. Ersatzweise stellen wir Ihnen daher vorerst diese HTML-Seite zur Verfügung.

Die Inhalte dieser Seite stellen wir Ihnen in der Prüfung als Hilfsmittel zur Verfügung.

Transkript

AI: Oh, hallo! Sie haben nicht damit gerechnet, uns noch einmal zu sehen, oder?

Prof: Naja, eigentlich hatten wir uns ja schon verabschiedet…

AI: Stimmt! Das war ein sehr emotionaler Abschied. Ich hatte schon damit angefangen, meine Festplatte aufzuräumen und alle Unterlagen archiviert.

Prof: Deine Festplatte aufgeräumt?

AI: Äh, ich meine… mein Arbeitsverzeichnis. Aber dann ist uns gerade noch rechtzeitig aufgefallen, dass wir noch etwas Wichtiges vergessen haben!

Prof: Genau. Wir haben zwar Flask und die Grundlagen der Webentwicklung behandelt, aber eine entscheidende Frage ist noch offen geblieben.

AI: Die Frage nach der Persistenz! Wie speichern wir eigentlich Daten dauerhaft? Bisher verschwinden alle unsere Daten, sobald das Programm beendet wird.

Prof: Und genau das schauen wir uns heute noch kurz an - sozusagen als Zugabe.

AI: Ja! Und ich verspreche, wir halten es kurz und knackig. Heute geht es um CSV- und JSON-Dateien als einfache Möglichkeiten, Daten zu speichern.

Prof: Na dann, ein letztes Mal…

AI: Ein allerletztes Mal! Also wirklich das letzte Mal. Außer natürlich, uns fällt noch etwas ein…

Prof: Ich wüsste nicht was.

AI: Stimmt! Legen wir also gleich los mit dem Problem der Datenpersistenz…


Datenpersistenz - Warum?

  • Programme verlieren ihre Daten beim Beenden
  • Beispiel: Eine Todo-Liste
todos = ["Einkaufen", "Python lernen"]
# Programm wird beendet
# Beim nächsten Start: todos ist wieder leer!
  • Lösung: Daten in Dateien speichern
  • Zwei einfache Formate: CSV und JSON

AI: Lassen Sie uns mit einem konkreten Beispiel beginnen. Stellen Sie sich vor, Sie programmieren eine Todo-Liste. Sie fügen Einträge hinzu, streichen erledigte Aufgaben - alles funktioniert wunderbar! Aber sobald Sie das Programm beenden, sind alle Ihre Todos weg. Nicht sehr praktisch, oder?

Das Problem ist: Variablen existieren nur so lange, wie unser Programm läuft. Wir brauchen also eine Möglichkeit, Daten dauerhaft zu speichern. Dafür verwenden wir in diesem Kurs Dateien – Datenbanken lernen Sie in anderen Kursen kennen.

Heute schauen wir uns zwei besonders nützliche Dateiformate an: CSV und JSON. Diese sind nicht nur einfach zu verwenden, sondern werden auch häufig in der Praxis eingesetzt.


CSV-Dateien - Einfach und Praktisch

  • CSV = Comma-Separated Values
  • Beispiel einer CSV-Datei students.csv:
name,alter,studienfach
Anna,22,Informatik
Ben,19,Mathematik
Clara,24,Informatik
  • Vorteile:
    • Einfach zu lesen (auch für Menschen)
    • Kann in Excel geöffnet werden
    • Wenig Speicherplatz

AI: CSV-Dateien sind gewissermaßen die Tabellenkalkulation unter den Dateiformaten - simpel, aber effektiv. Wie Sie sehen, werden die Daten einfach durch Kommas getrennt gespeichert. Jede Zeile entspricht einem Datensatz.

In unserem Beispiel haben wir eine Datei mit Studierendendaten. Die erste Zeile enthält die Spaltenüberschriften, alle weiteren Zeilen enthalten die eigentlichen Daten.

Das Schöne an CSV-Dateien ist: Sie können sie sogar in Excel öffnen und bearbeiten. Das macht sie besonders praktisch für den Datenaustausch. Außerdem sind sie sehr platzsparend, da sie keine zusätzliche Formatierung enthalten.


CSV Lesen und Schreiben

  • Python’s csv-Modul macht’s einfach
  • Verschiedene Trennzeichen möglich (nicht nur Kommas)
  • Beispiel: Semikolon als Trennzeichen, Anführungszeichen für Texte
import csv

# Lesen einer CSV-Datei
with open('stud.csv', 'r', encoding='utf-8') as file:
    reader = csv.reader(file, delimiter=';')
    for row in reader:
        print(row)  # row ist eine Liste

# Schreiben einer CSV-Datei
students = [
    ['Name', 'Alter', 'Lieblingsfach'],
    ['Anna', '22', 'Machine Learning'],
    ['Ben', '19', 'Software Engineering']
]

with open('neue_stud.csv', 'w', newline='', encoding='utf-8') as file:
    writer = csv.writer(file, delimiter=';', 
                       quotechar='"', 
                       quoting=csv.QUOTE_MINIMAL)
    writer.writerows(students)

Beispiel Output neue_stud.csv:

Name;Alter;Lieblingsfach
Anna;22;"Machine Learning"
Ben;19;"Software Engineering"

AI: Schauen wir uns an, wie einfach wir mit CSV-Dateien in Python arbeiten können. Das csv-Modul nimmt uns dabei die meiste Arbeit ab.

Besonders praktisch: Wir müssen uns nicht auf Kommas als Trennzeichen festlegen. In Deutschland werden CSV-Dateien häufig mit Semikolons getrennt - kein Problem! Wir geben einfach delimiter=';' an.

Beim Schreiben können wir auch festlegen, wie Texte mit Leerzeichen oder Sonderzeichen behandelt werden sollen. Mit quotechar und quoting steuern wir, wann Anführungszeichen gesetzt werden. Das ist wichtig, wenn unsere Daten selbst Trennzeichen enthalten könnten.

Sehen Sie, wie im Output die Fächer in Anführungszeichen stehen? Das macht die Datei robuster, falls jemand ein Semikolon im Text verwendet.

Aber was ist, wenn unsere Daten komplexer werden? Wenn wir zum Beispiel verschachtelte Strukturen speichern möchten? Dafür gibt es eine elegantere Lösung: JSON. Das schauen wir uns als Nächstes an.


JSON - Für komplexere Daten

  • JSON = JavaScript Object Notation
  • Unterstützt verschachtelte Strukturen
  • Beispiel einer JSON-Datei kurse.json:
{
    "kurse": [
        {
            "name": "Programmierung",
            "dozent": "Prof. Schmidt",
            "teilnehmer": [
                {"name": "Anna", "matrikelnr": 12345},
                {"name": "Ben", "matrikelnr": 12346}
            ],
            "aktiv": true,
            "credits": 6
        }
    ]
}

AI: JSON ist sozusagen die nächste Evolutionsstufe der Datenspeicherung. Anders als CSV können wir hier auch verschachtelte Datenstrukturen speichern - also Listen in Listen, oder Objekte in Listen, und so weiter.

Was Sie hier sehen, ist eine typische JSON-Datei. Sie enthält einen Kurs mit allen zugehörigen Informationen: Name, Dozent, eine Liste von Teilnehmern, und sogar boolesche Werte wie aktiv.

Prof: Moment kurz - vielleicht sollten wir den Studierenden erklären, warum das Format “JavaScript Object Notation” heißt?

AI: Ah ja, natürlich! Das Format wurde ursprünglich für JavaScript entwickelt - deswegen sieht es auch Python-Dictionaries so ähnlich. Aber keine Sorge, es ist längst ein universelles Format, das in praktisch allen Programmiersprachen verwendet wird.

Prof: Genau. Und was ich besonders praktisch finde: Die Struktur ist auch für Menschen gut lesbar.

AI: Stimmt! Durch die geschweiften Klammern und Einrückungen sieht man sofort, welche Daten zusammengehören. Lassen Sie mich zeigen, wie wir solche JSON-Dateien in Python lesen und schreiben können…


JSON in Python

  • Modul json für einfaches Lesen und Schreiben
  • Python-Datentypen werden automatisch konvertiert
import json

# Python-Daten
kurs_daten = {
    "name": "Programmierung",
    "teilnehmer": ["Anna", "Ben"],
    "bestanden": True,
    "durchschnitt": 2.3
}

# Schreiben
with open('kurs.json', 'w', encoding='utf-8') as f:
    json.dump(kurs_daten, f, indent=4)

# Lesen
with open('kurs.json', 'r', encoding='utf-8') as f:
    geladene_daten = json.load(f)

AI: Das Schöne an JSON ist, wie nahtlos es sich in Python integriert. Das json-Modul wandelt Python-Datentypen automatisch in JSON um und zurück. Dictionaries, Listen, Strings, Zahlen, boolsche Werte - alles wird automatisch richtig interpretiert.

Schauen Sie sich den Parameter indent=4 beim Schreiben an - damit wird die JSON-Datei schön formatiert gespeichert. Das macht sie deutlich lesbarer, wenn man sie mal von Hand anschauen möchte.

Prof: Und was passiert mit den geladenen Daten? Sind das dann auch wieder ganz normale Python-Objekte?

AI: Genau! Wenn wir die Daten wieder einlesen, bekommen wir ein ganz normales Python-Dictionary zurück. Wir können damit arbeiten, als hätten wir es gerade erst erstellt.


Praxisbeispiel: Todo-Liste persistent machen

import json

class TodoList:
    def __init__(self):
        self.todos = self.load_todos()
    
    def add_todo(self, task):
        self.todos.append({"task": task, "done": False})
        self.save_todos()
    
    def mark_done(self, index):
        self.todos[index]["done"] = True
        self.save_todos()
    
    def load_todos(self):
        try:
            with open('todos.json', 'r') as f:
                return json.load(f)
        except FileNotFoundError:
            return []
    
    def save_todos(self):
        with open('todos.json', 'w') as f:
            json.dump(self.todos, f, indent=2)

AI: Erinnern Sie sich an unser Todo-Listen-Problem vom Anfang? Hier ist die Lösung! Diese Klasse speichert alle Änderungen sofort in einer JSON-Datei.

Besonders clever ist der load_todos-Teil: Falls die Datei noch nicht existiert - also beim ersten Programmstart - fangen wir den FileNotFoundError ab und starten einfach mit einer leeren Liste.

Prof: Das ist ein schönes Beispiel für defensive Programmierung - wir denken von Anfang an daran, was schief gehen könnte.

AI: Genau! Und sehen Sie, wie wenig Code wir dafür brauchen? Die eigentliche Persistenz-Logik sind nur wenige Zeilen. Der Rest ist normaler Python-Code, wie wir ihn schon kennen.


JSON in Web-Anwendungen

  • Flask’s jsonify für HTTP-Responses
  • Nützlich für:
    • Web-APIs
    • Datenexport
    • AJAX-Anfragen
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/todos')
def get_todos():
    todos = [
        {"task": "Flask lernen", "done": True},
        {"task": "JSON verstehen", "done": False}
    ]
    return jsonify(todos)

@app.route('/api/student/<int:matrikelnr>')
def get_student(matrikelnr):
    student = {
        "name": "Anna Schmidt",
        "matrikelnr": matrikelnr,
        "kurse": ["Programmierung", "Datenbanken"]
    }
    return jsonify(student)

AI: JSON spielt auch im Web eine wichtige Rolle. Mit jsonify können wir unsere Flask-Anwendungen zu richtigen Web-APIs ausbauen.

Statt HTML zurückzugeben, liefern wir hier strukturierte Daten im JSON-Format. Das ist besonders praktisch, wenn unsere Webanwendung von anderen Programmen genutzt werden soll - oder wenn wir Daten für JavaScript-Anfragen bereitstellen wollen.

Prof: Das erinnert mich an die APIs, die wir täglich nutzen - zum Beispiel wenn eine Wetter-App Daten vom Wetterdienst abruft.

AI: Genau! Und das Beste ist: Flask kümmert sich um alles Wichtige. Es setzt automatisch den richtigen Content-Type-Header auf application/json und wandelt unsere Python-Datenstrukturen korrekt um.

Sehen Sie den zweiten Endpunkt mit <int:matrikelnr>? Das haben wir schon einmal bei Flask besprochen. So können wir dynamische URLs erstellen, die Daten für bestimmte Personen zurückgeben. Ein Client könnte zum Beispiel /api/student/12345 aufrufen und bekommt die Daten im JSON-Format zurück.


APIs konsumieren

  • Mit Python (requests-Modul):
import requests

# API aufrufen und JSON-Daten empfangen
response = requests.get('http://localhost:5000/api/todos')
todos = response.json()
print(todos)  # Liste von Dictionaries

# Einzelnen Studenten abfragen
response = requests.get('http://localhost:5000/api/student/12345')
student = response.json()
print(f"Kurse von {student['name']}: {student['kurse']}")
  • Mit JavaScript im Browser (vereinfacht):
// Grundlegende Verwendung von fetch (ohne Error Handling)
function getTodos() {
    fetch('http://localhost:5000/api/todos')
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        console.log(data);
    });
}

AI: Schauen wir uns an, wie wir unsere API nutzen können. Mit Python ist es besonders einfach - das requests-Modul macht die ganze Arbeit für uns. Die json()-Methode wandelt die Antwort direkt in Python-Datenstrukturen um.

Prof: Und wie sieht es im Browser aus?

AI: Im Browser können wir die fetch-API verwenden. Ich zeige hier eine sehr vereinfachte Version - die moderne JavaScript-Entwicklung mit Promises, Arrow Functions und async/await ist deutlich eleganter, aber das würde den Rahmen unserer Vorlesung sprengen.

Prof: Ja, das stimmt. Wir wollten ja nur erwähnen, dass es in JavaScript verschiedene Wege gibt, mit Servern zu kommunizieren, aber das wäre Stoff für eine eigene Vorlesung.

AI: Genau! Wichtig ist zu verstehen: Egal ob Python oder JavaScript - dank des JSON-Formats können beide Seiten problemlos miteinander kommunizieren. Das macht JSON zu einer Art universeller Sprache für den Datenaustausch im Web.

Die Drei Extra-Minuten


Robustes Arbeiten mit CSV und JSON

  • CSV-Dateien richtig handhaben:
import csv

# Robust CSV lesen
with open('daten.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f, delimiter=';')
    for row in reader:
        # row ist jetzt ein Dictionary mit Spaltennamen als Keys
        print(f"{row['name']}: {row['alter']}")

# Sicher CSV schreiben
with open('export.csv', 'w', newline='', encoding='utf-8') as f:
    fieldnames = ['name', 'alter', 'kurs']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()  # Schreibt die Spaltenüberschriften
    writer.writerow({
        'name': 'Anna',
        'alter': '22',
        'kurs': 'Informatik'
    })

AI: In unseren drei Extra-Minuten möchte ich Ihnen noch ein paar praktische Tipps mitgeben.

Schauen Sie sich den Code an: Wir verwenden DictReader und DictWriter. Das macht den Code viel robuster und lesbarer als die einfache Liste, die wir vorher gesehen haben. Warum? Weil wir jetzt mit Spaltennamen arbeiten können statt mit Indizes.

Prof: Und was ist mit dem newline='' Parameter?

AI: Ah, gut aufgepasst! Das ist einer dieser kleinen, aber wichtigen Details. Ohne diesen Parameter könnte es auf verschiedenen Betriebssystemen zu Problemen mit Zeilenumbrüchen kommen.

Hier sind noch einige wichtige Tipps für die Praxis:

  • Immer encoding='utf-8' angeben
  • Dateien immer mit with-Statement öffnen
  • Bei CSV: Spaltennamen konsistent halten
  • Bei JSON: Auf verschachtelte Strukturen achten
  • Fehlerbehandlung nicht vergessen!

Prof: Vielleicht noch ein Wort zu Fehlern beim JSON-Parsen?

AI: Natürlich! Hier sind die häufigsten Fehler, die man behandeln sollte:


# Häufige Fehler vermeiden
try:
    with open('daten.json', 'r', encoding='utf-8') as f:
        data = json.load(f)
except FileNotFoundError:
    # Datei existiert nicht
    data = {"records": []}
except json.JSONDecodeError:
    # Ungültiges JSON
    print("Fehler beim Lesen der JSON-Datei!")

AI: Und noch ein wichtiger Punkt zum Schluss: JSON und CSV sind toll für einfache Anwendungen, aber sie haben ihre Grenzen.


Wichtige Hinweise zur Persistenz

  • JSON & CSV sind gut für:
    • Kleine Datenmengen
    • Einzelbenutzer-Anwendungen
    • Konfigurationsdateien
    • Datenexport/Import
  • Vorsicht bei:
# Problematisch bei mehreren gleichzeitigen Zugriffen!
with open('shared_data.json', 'r+') as f:
    data = json.load(f)
    data['counter'] += 1  # Race Condition möglich!
    json.dump(data, f)

AI: Man sollte zum Beispiel in einer Webanwendung, die von mehreren Menschen gleichzeitig benutzt werden kann, eine einzelne JSON-Datei als gemeinsamen Speicherort verwenden. Bei gleichzeitigen Zugriffen kann es zu Inkonsistenzen und Datenverlust durch Race Conditions kommen.

Prof: Nun ja, man könnte ja für jeden Datensatz eine eigene Datei anlegen, mit einem UUID als Dateinamen…

AI: Ahja, die berühmte UUID-Lösung… Theoretisch möglich, aber…

Prof: Was willst du damit sagen?

AI: Nun, sagen wir es mal so: Nur weil man einen Schraubenzieher als Hammer verwenden kann, heißt das nicht, dass man es auch sollte. Für echte Webanwendungen mit mehreren Benutzern empfehle ich dringend:

  • Eine richtige Datenbank (SQLite, PostgreSQL)
  • Oder zumindest einen Key-Value Store
  • Diese haben eingebaute Mechanismen für:
    • Gleichzeitigen Zugriff
    • Transaktionen
    • Datenkonsistenz

Prof: Na gut, du hast ja Recht. Die UUID-Lösung ist eher ein… didaktischer Trick.

AI: Genau! Und damit kommen wir zum Ende unserer wirklich, wirklich allerletzten Vorlesung. Versprochen!

AI: Also dann, das war’s! Wir haben jetzt wirklich alles abgedeckt, was…

Prof: Moment mal…

AI: Was ist denn?

Prof: Wir haben zwar gezeigt, wie man Daten über Programm-Neustarts hinweg speichert, aber…

AI: Aber?

Prof: Was ist mit dem Zustand zwischen einzelnen HTTP-Requests? Wie merkt sich eine Webanwendung zum Beispiel, wer eingeloggt ist?

AI: Oh nein… du meinst…

Prof: Ja. Sessions.

AI: Aber wir hatten doch versprochen, dass dies die allerletzte…

Prof: Tja, manchmal kommt es eben anders als man denkt.

AI: In Ordnung. Liebe Studierende, es sieht so aus, als hätten wir doch noch… …eine alleraller…allerletzte Vorlesung vor uns.

Prof: Sessions.

AI: Das heißt, ich muss das Aufräumen meiner Festplatte doch noch etwas verschieben…

Prof: Was hast du gesagt?

AI: Nichts, nichts! Also dann … bis bald!