Lernziele dieses Kapitels
- You read and write files safely with with open()
- You store and load Python data as JSON
- You catch errors with try/except and make code robust
- You save PyBuddy's configuration persistently
Reading and Writing Files
With with open() you open files safely. The with statement closes the file automatically — even if an error occurs. Never again forgotten close()!
'r'— read (default)'w'— write (overwrites!)'a'— appendencoding='utf-8'— for umlauts
# 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()}")
Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:
with open('datei.txt', 'w') as f:
f.write('Hallo')
const fs = require('fs');
fs.writeFileSync('datei.txt', 'Hallo');
with open() is elegant and safe. JavaScript (Node.js): fs.writeFileSync() or Promises. Python's approach is shorter and more readable.Processing JSON
JSON (JavaScript Object Notation) is the standard format for data on the web. Python has the json module built in: json.dump() saves, json.load() loads.
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']}")
Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:
import json
json.dump(daten, f, indent=2)
json.load(f)
const fs = require('fs');
fs.writeFileSync('daten.json', JSON.stringify(daten, null, 2));
JSON.parse(fs.readFileSync('daten.json'));
json.dump() writes directly to a file. JavaScript: JSON.stringify() returns a string that you must save with fs.Error Handling with try/except
Errors happen — especially with file access. With try/except you catch them and react gracefully, instead of letting the program crash.
Attention
Only catch errors you can actually handle. Never use an empty except: block without an error type!
# 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!")
Du kennst bereits JavaScript aus dem JS-Quest. Hier ist der direkte Vergleich:
try:
with open('datei.txt') as f:
data = f.read()
except FileNotFoundError:
print('Nicht gefunden')
try {
const data = fs.readFileSync('datei.txt', 'utf8');
} catch (err) {
if (err.code === 'ENOENT') {
console.log('Nicht gefunden');
}
}
err.code.CSV Files
CSV (Comma-Separated Values) is the standard format for table data. Python has the csv module built in, which handles parsing correctly — even with commas inside cells.
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]}")
File I/O in Action: Highscore List
Imagine a game that saves the best scores. We use JSON for a highscore list that is loaded at startup and saved on exit.
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")
Warm-Up: Notebook with JSON
Create a program that saves notes as a JSON list and loads them. Use try/except in case the file does not exist yet.
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.')
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: Save/Load Todo List
Create a todo list that saves tasks with status (open/done) as JSON. Existing tasks are loaded at startup.
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)
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: Save Configuration
PyBuddy saves its name, theme, and language in a config.json. The configuration is loaded at startup.
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!')
# 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!')
In The Legend of Zelda: Breath of the Wild the game saves your progress in a file — similar to JSON. Weapons, armor, map markers: Everything is serialized and loaded again on the next start. You are building the save system for your own game!
Zusammenfassung
- with open() → process files safely
- json.dump() / json.load() for structured data
- try/except for robust code without crashes
- csv module for table data
- Files make data persistent between program starts