DE EN

File I/O & JSON

Dateien lesen und schreiben, Konfigurationen speichern, JSON-Daten verarbeiten.

50 Min Mittel

Lernziele dieses Kapitels

  • Du liest und schreibst Dateien sicher mit with open()
  • Du speicherst und lädst Python-Daten als JSON
  • Du fängst Fehler mit try/except ab und machst Code robust
  • Du speicherst PyBuddy's Konfiguration persistent

Dateien lesen und schreiben

Mit with open() öffnest du Dateien sicher. Das with-Statement schließt die Datei automatisch — auch wenn ein Fehler auftritt. Nie wieder vergessene close()!

  • 'r' — lesen (Standard)
  • 'w' — schreiben (überschreibt!)
  • 'a' — anhängen
  • encoding='utf-8' — für Umlaute
Python
# Datei schreiben
with open("notiz.txt", "w", encoding="utf-8") as f:
    f.write("Python ist cool!\n")
    f.write("Heute lerne ich File I/O.\n")

# Datei lesen
with open("notiz.txt", "r", encoding="utf-8") as f:
    inhalt = f.read()
    print(inhalt)

# Zeile für Zeile lesen
with open("notiz.txt", "r", encoding="utf-8") as f:
    for zeile in f:
        print(f"→ {zeile.strip()}")
Ausgabe
Python ist cool! Heute lerne ich File I/O. → Python ist cool! → Heute lerne ich File I/O.
Python vs. JavaScript — Das kennst du schon!

Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:

Python
with open('datei.txt', 'w') as f:
    f.write('Hallo')
JavaScript
const fs = require('fs');
fs.writeFileSync('datei.txt', 'Hallo');
Merke: Python: with open() ist elegant und sicher. JavaScript (Node.js): fs.writeFileSync() oder Promises. Python's Ansatz ist kürzer und lesbarer.

JSON verarbeiten

JSON (JavaScript Object Notation) ist das Standardformat für Daten im Web. Python hat das json-Modul eingebaut: json.dump() speichert, json.load() lädt.

Python
import json

# Dictionary als JSON speichern
spieler = {
    "name": "PyKnight",
    "level": 5,
    "items": ["Schwert", "Schild"]
}

with open("spieler.json", "w", encoding="utf-8") as f:
    json.dump(spieler, f, indent=2, ensure_ascii=False)

# JSON laden
with open("spieler.json", "r", encoding="utf-8") as f:
    geladen = json.load(f)

print(geladen["name"])
print(f"Items: {geladen['items']}")
Ausgabe
PyKnight Items: ['Schwert', 'Schild']
Python vs. JavaScript — Das kennst du schon!

Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:

Python
import json
json.dump(daten, f, indent=2)
json.load(f)
JavaScript
const fs = require('fs');
fs.writeFileSync('daten.json', JSON.stringify(daten, null, 2));
JSON.parse(fs.readFileSync('daten.json'));
Merke: Python: json.dump() schreibt direkt in eine Datei. JavaScript: JSON.stringify() gibt einen String zurück, den du mit fs speichern musst.

Error Handling mit try/except

Fehler passieren — besonders beim Dateizugriff. Mit try/except fängst du sie ab und reagierst elegant, anstatt dass das Programm abstürzt.

Achtung

Fange nur Fehler ab, die du auch behandeln kannst. Niemals einen leeren except: Block ohne Fehlertyp verwenden!

Python
# Robuster Dateizugriff
try:
    with open("config.json", "r", encoding="utf-8") as f:
        config = json.load(f)
        print(f"Theme: {config['theme']}")
except FileNotFoundError:
    print("  config.json nicht gefunden. Erstelle Standard-Konfiguration.")
    config = {"theme": "dark", "sprache": "de"}
except json.JSONDecodeError:
    print(" config.json ist beschädigt!")
    config = {"theme": "dark"}

# Mehrere Fehlertypen
try:
    zahl = int(input("Zahl: "))
    ergebnis = 100 / zahl
    print(f"Ergebnis: {ergebnis}")
except ValueError:
    print(" Das war keine gültige Zahl!")
except ZeroDivisionError:
    print(" Division durch Null ist nicht erlaubt!")
Ausgabe
config.json nicht gefunden. Erstelle Standard-Konfiguration. Zahl: 0 Division durch Null ist nicht erlaubt!
Python vs. JavaScript — Das kennst du schon!

Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:

Python
try:
    with open('datei.txt') as f:
        data = f.read()
except FileNotFoundError:
    print('Nicht gefunden')
JavaScript
try {
    const data = fs.readFileSync('datei.txt', 'utf8');
} catch (err) {
    if (err.code === 'ENOENT') {
        console.log('Nicht gefunden');
    }
}
Merke: Python und JavaScript haben beide try/catch (bzw. try/except). Python unterscheidet Fehlertypen sauberer, in JS prüfst du oft err.code.

CSV-Dateien

CSV (Comma-Separated Values) ist das Standardformat für Tabellen-Daten. Python hat das csv-Modul eingebaut, das das Parsing korrekt handhabt — auch bei Kommas in Zellen.

Python
import csv

# CSV schreiben
with open("noten.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["Name", "Fach", "Note"])
    writer.writerow(["Anna", "Mathe", 1])
    writer.writerow(["Ben", "Englisch", 2])

# CSV lesen
with open("noten.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    for row in reader:
        print(f"{row[0]:10} | {row[1]:10} | {row[2]}")
Ausgabe
Name | Fach | Note Anna | Mathe | 1 Ben | Englisch | 2

File I/O in Aktion: Highscore-Liste

Stell dir ein Spiel vor, das die besten Punktestände speichert. Wir nutzen JSON für eine Highscore-Liste, die beim Start geladen und beim Beenden gespeichert wird.

Python
import json

# Highscore laden oder erstellen
try:
    with open("highscores.json", "r", encoding="utf-8") as f:
        scores = json.load(f)
except FileNotFoundError:
    scores = []

# Neuen Score hinzufügen
name = input("Dein Name: ")
punkte = int(input("Deine Punkte: "))
scores.append({"name": name, "punkte": punkte})

# Sortieren (absteigend)
scores.sort(key=lambda x: x["punkte"], reverse=True)

# Top 5 speichern
scores = scores[:5]
with open("highscores.json", "w", encoding="utf-8") as f:
    json.dump(scores, f, indent=2, ensure_ascii=False)

print("\n Highscores:")
for i, s in enumerate(scores, 1):
    print(f"  {i}. {s['name']}: {s['punkte']} Punkte")
Ausgabe
Dein Name: Max Deine Punkte: 1250 Highscores: 1. Max: 1250 Punkte

Warm-Up: Notizbuch mit JSON

Erstelle ein Programm, das Notizen als JSON-Liste speichert und lädt. Nutze try/except für den Fall, dass die Datei noch nicht existiert.

Hinweis: import json try: with open('notizen.json', 'r') as f: notizen = json.load(f) except FileNotFoundError: notizen = [] text = input('Neue Notiz: ') notizen.append(text) with open('notizen.json', 'w') as f: json.dump(notizen, f, indent=2) print(f' {len(notizen)} Notiz(en) gespeichert.')

Lösung
import json

try:
    with open('notizen.json', 'r') as f:
        notizen = json.load(f)
except FileNotFoundError:
    notizen = []

text = input('Neue Notiz: ')
notizen.append(text)

with open('notizen.json', 'w') as f:
    json.dump(notizen, f, indent=2)

print(f' {len(notizen)} Notiz(en) gespeichert.')

Challenge: Todo-Liste speichern/laden

Erstelle eine Todo-Liste, die Aufgaben mit Status (offen/erledigt) als JSON speichert. Beim Start werden vorhandene Aufgaben geladen.

Hinweis: import json try: with open('todos.json', 'r') as f: todos = json.load(f) except FileNotFoundError: todos = [] while True: cmd = input('[add, list, save, exit] ').lower() if cmd == 'exit': break elif cmd == 'add': task = input('Aufgabe: ') todos.append({'task': task, 'done': False}) elif cmd == 'list': for i, t in enumerate(todos, 1): status = '' if t['done'] else '⬜' print(f' {i}. {status} {t["task"]}') elif cmd == 'save': with open('todos.json', 'w') as f: json.dump(todos, f, indent=2)

Lösung
import json

try:
    with open('todos.json', 'r') as f:
        todos = json.load(f)
except FileNotFoundError:
    todos = []

while True:
    cmd = input('[add, list, save, exit] ').lower()
    if cmd == 'exit': break
    elif cmd == 'add':
        task = input('Aufgabe: ')
        todos.append({'task': task, 'done': False})
    elif cmd == 'list':
        for i, t in enumerate(todos, 1):
            status = '' if t['done'] else '⬜'
            print(f'  {i}. {status} {t["task"]}')
    elif cmd == 'save':
        with open('todos.json', 'w') as f:
            json.dump(todos, f, indent=2)

PyBuddy-Checkpoint: Konfiguration speichern

PyBuddy speichert seinen Namen, das Theme und die Sprache in einer config.json. Beim Start wird die Konfiguration geladen.

Hinweis: # pybuddy/main.py import json def lade_config(): try: with open('config.json', 'r') as f: return json.load(f) except FileNotFoundError: return {'name': 'PyBuddy', 'theme': 'dark', 'sprache': 'de'} def speichere_config(config): with open('config.json', 'w') as f: json.dump(config, f, indent=2) config = lade_config() print(f" {config['name']} startet...") print(f"🎨 Theme: {config['theme']}") config['name'] = input('Neuer Name: ') or config['name'] speichere_config(config) print('💾 Konfiguration gespeichert!')

Lösung
# pybuddy/main.py
import json

def lade_config():
    try:
        with open('config.json', 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        return {'name': 'PyBuddy', 'theme': 'dark', 'sprache': 'de'}

def speichere_config(config):
    with open('config.json', 'w') as f:
        json.dump(config, f, indent=2)

config = lade_config()
print(f" {config['name']} startet...")
print(f"🎨 Theme: {config['theme']}")
config['name'] = input('Neuer Name: ') or config['name']
speichere_config(config)
print('💾 Konfiguration gespeichert!')
Didaktische Pause

In The Legend of Zelda: Breath of the Wild speichert das Spiel deinen Fortschritt in einer Datei — ähnlich wie JSON. Waffen, Rüstungen, Karten-Markierungen: Alles wird serialisiert und beim nächsten Start wieder geladen. Du baust gerade das Speichersystem für dein eigenes Spiel!

Zusammenfassung

  • with open() → sicher Dateien verarbeiten
  • json.dump() / json.load() für strukturierte Daten
  • try/except für robusten Code ohne Abstürze
  • csv-Modul für Tabellen-Daten
  • Dateien machen Daten persistent zwischen Programmstarts