Dateien lesen und schreiben in Python
Lerne, wie du in Python Dateien oeffnest, liest, schreibst und mit verschiedenen Formaten wie CSV und JSON arbeitest -- inklusive Best Practices mit dem with-Statement.
Warum Dateien?
Programme arbeiten mit Daten — aber was passiert, wenn du das Programm beendest? Ohne Dateien sind alle Daten weg. Dateien ermoeglichten es dir, Daten dauerhaft zu speichern und spaeter wieder zu laden.
Typische Anwendungsfaelle:
- Konfigurationsdateien lesen (Einstellungen deiner App)
- Benutzerdaten speichern (Notizen, Highscores, Kontakte)
- Logdateien schreiben (was ist im Programm passiert?)
- Daten austauschen (CSV-Export fuer Excel, JSON fuer APIs)
# Stell dir vor: Dein Programm speichert Notizen
notizen = ["Einkaufen gehen", "Python lernen", "Sport machen"]
# Ohne Dateien: Alles weg nach Programmende!
# Mit Dateien: Daten bleiben erhalten
Die open() Funktion
Die eingebaute Funktion open() ist dein Tor zur Dateiwelt. Sie oeffnet eine Datei und gibt ein Dateiobjekt zurueck, mit dem du arbeiten kannst.
# Grundsyntax
datei = open("meine_datei.txt", "r")
# ... mit der Datei arbeiten ...
datei.close() # Wichtig: Datei wieder schliessen!
Dateimodi
Der zweite Parameter bestimmt, was du mit der Datei machen willst:
| Modus | Bedeutung | Datei existiert nicht? |
|---|---|---|
"r" | Read — Lesen (Standard) | Fehler! |
"w" | Write — Schreiben (ueberschreibt!) | Wird erstellt |
"a" | Append — Anhaengen | Wird erstellt |
"x" | Exclusive — Erstellen (nur wenn neu) | Wird erstellt, Fehler wenn existiert |
# Lesen -- Datei muss existieren
datei = open("daten.txt", "r")
# Schreiben -- ACHTUNG: Inhalt wird ueberschrieben!
datei = open("daten.txt", "w")
# Anhaengen -- fuegt am Ende hinzu
datei = open("daten.txt", "a")
# Exklusiv erstellen -- Fehler wenn Datei schon existiert
datei = open("neue_datei.txt", "x")
Das with-Statement — immer verwenden!
Das groesste Problem mit open() und close(): Was passiert, wenn zwischen dem Oeffnen und Schliessen ein Fehler auftritt? Dann wird close() nie aufgerufen und die Datei bleibt gesperrt.
Die Loesung: Das with-Statement (Context Manager). Es schliesst die Datei automatisch, egal was passiert:
# SO solltest du es IMMER machen:
with open("meine_datei.txt", "r") as datei:
inhalt = datei.read()
print(inhalt)
# Hier ist die Datei automatisch geschlossen!
# NICHT so (veraltet und fehleranfaellig):
datei = open("meine_datei.txt", "r")
inhalt = datei.read()
datei.close()
Merke dir: Verwende immer
with open(...) as ...:— es gibt keinen guten Grund, es nicht zu tun.
Textdateien lesen
Es gibt drei Methoden, um Text aus einer Datei zu lesen:
read() — Alles auf einmal
with open("gedicht.txt", "r") as datei:
gesamter_text = datei.read()
print(gesamter_text)
read() gibt den gesamten Inhalt als einen einzigen String zurueck. Bei grossen Dateien kann das viel Speicher verbrauchen.
readline() — Zeile fuer Zeile
with open("gedicht.txt", "r") as datei:
erste_zeile = datei.readline()
zweite_zeile = datei.readline()
print(erste_zeile)
print(zweite_zeile)
Jeder Aufruf von readline() liest die naechste Zeile. Am Dateiende gibt es einen leeren String "" zurueck.
readlines() — Alle Zeilen als Liste
with open("gedicht.txt", "r") as datei:
alle_zeilen = datei.readlines()
print(alle_zeilen)
# ['Erste Zeile\n', 'Zweite Zeile\n', 'Dritte Zeile\n']
Die eleganteste Methode: Ueber die Datei iterieren
with open("gedicht.txt", "r") as datei:
for zeile in datei:
print(zeile.strip()) # strip() entfernt \n am Ende
Das ist speichereffizient, weil immer nur eine Zeile im Speicher liegt — perfekt fuer grosse Dateien!
Textdateien schreiben
write() — Text schreiben
with open("ausgabe.txt", "w") as datei:
datei.write("Hallo Welt!\n")
datei.write("Dies ist Zeile 2.\n")
datei.write("Und Zeile 3.\n")
Wichtig: write() fuegt keinen automatischen Zeilenumbruch hinzu. Du musst \n selbst anhaengen!
writelines() — Liste von Strings schreiben
zeilen = ["Apfel\n", "Birne\n", "Kirsche\n"]
with open("fruechte.txt", "w") as datei:
datei.writelines(zeilen)
Auch writelines() fuegt keine Zeilenumbrueche hinzu — du musst sie in den Strings selbst haben.
Trick: print() in Dateien umleiten
with open("ausgabe.txt", "w") as datei:
print("Das kommt in die Datei!", file=datei)
print("Auch das.", file=datei)
print(f"Ergebnis: {42 * 3}", file=datei)
Mit dem file-Parameter von print() kannst du die Ausgabe direkt in eine Datei umleiten — inklusive automatischem Zeilenumbruch!
Dateien anhaengen mit dem "a"-Modus
Wenn du Daten hinzufuegen willst, ohne den bestehenden Inhalt zu loeschen, nutze den Append-Modus:
# Logbuch fuehren
from datetime import datetime
def log_eintrag(nachricht):
with open("logbuch.txt", "a") as log:
zeitstempel = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log.write(f"[{zeitstempel}] {nachricht}\n")
log_eintrag("Programm gestartet")
log_eintrag("Benutzer eingeloggt")
log_eintrag("Daten gespeichert")
Das Logbuch waechst mit jedem Aufruf:
[2026-02-10 14:30:01] Programm gestartet
[2026-02-10 14:30:02] Benutzer eingeloggt
[2026-02-10 14:30:05] Daten gespeichert
Encoding — Zeichenkodierung beachten
Text wird in Dateien als Bytes gespeichert. Damit Umlaute (ae, oe, ue) und Sonderzeichen korrekt funktionieren, musst du die richtige Zeichenkodierung angeben:
# Immer UTF-8 verwenden -- der moderne Standard
with open("deutsch.txt", "w", encoding="utf-8") as datei:
datei.write("Gruesse aus Muenchen!\n")
datei.write("Schoene Ueberraschung!\n")
with open("deutsch.txt", "r", encoding="utf-8") as datei:
print(datei.read())
Ohne
encoding="utf-8"verwendet Python die Standardkodierung deines Betriebssystems, was auf Windows oftcp1252ist. Das fuehrt zu Problemen, wenn du Dateien zwischen Systemen austauschst. Gewoehn dir an, immerencoding="utf-8"anzugeben.
CSV-Dateien mit dem csv-Modul
CSV (Comma-Separated Values) ist ein einfaches Tabellenformat — perfekt fuer strukturierte Daten.
CSV schreiben
import csv
schueler = [
["Name", "Alter", "Note"],
["Anna", 16, 1.3],
["Ben", 17, 2.0],
["Clara", 16, 1.7],
]
with open("schueler.csv", "w", encoding="utf-8", newline="") as datei:
writer = csv.writer(datei)
writer.writerows(schueler)
Wichtig: newline="" verhindert leere Zeilen auf Windows!
CSV lesen
import csv
with open("schueler.csv", "r", encoding="utf-8") as datei:
reader = csv.reader(datei)
for zeile in reader:
print(zeile)
# ['Name', 'Alter', 'Note']
# ['Anna', '16', '1.3']
# ...
CSV mit Woerterbuch (DictReader / DictWriter)
import csv
# Lesen als Woerterbuch -- viel uebersichtlicher!
with open("schueler.csv", "r", encoding="utf-8") as datei:
reader = csv.DictReader(datei)
for zeile in reader:
print(f"{zeile['Name']} hat die Note {zeile['Note']}")
JSON-Dateien mit dem json-Modul
JSON (JavaScript Object Notation) ist das Standardformat fuer den Datenaustausch im Web. Python-Dicts und JSON passen perfekt zusammen.
JSON schreiben
import json
einstellungen = {
"benutzername": "max_mustermann",
"design": "dunkel",
"sprache": "de",
"benachrichtigungen": True,
"favoriten": ["Python", "JavaScript", "Rust"]
}
with open("config.json", "w", encoding="utf-8") as datei:
json.dump(einstellungen, datei, indent=4, ensure_ascii=False)
indent=4sorgt fuer huebsche Formatierungensure_ascii=Falseerlaubt Umlaute in der Ausgabe
JSON lesen
import json
with open("config.json", "r", encoding="utf-8") as datei:
einstellungen = json.load(datei)
print(einstellungen["benutzername"]) # max_mustermann
print(einstellungen["favoriten"]) # ['Python', 'JavaScript', 'Rust']
JSON und Strings
import json
# Python-Objekt -> JSON-String
daten = {"name": "Anna", "alter": 25}
json_string = json.dumps(daten, indent=2)
print(json_string)
# JSON-String -> Python-Objekt
wieder_daten = json.loads(json_string)
print(wieder_daten["name"]) # Anna
Merke: dump/load arbeiten mit Dateien, dumps/loads arbeiten mit Strings (das “s” steht fuer “string”).
pathlib.Path — Moderner Umgang mit Pfaden
Das pathlib-Modul ist der moderne Weg, mit Dateipfaden zu arbeiten. Es ist objektorientiert und plattformunabhaengig.
from pathlib import Path
# Pfad erstellen
pfad = Path("daten") / "projekte" / "notizen.txt"
print(pfad) # daten/projekte/notizen.txt (bzw. daten\projekte\notizen.txt auf Windows)
# Nuetzliche Eigenschaften
print(pfad.name) # notizen.txt
print(pfad.stem) # notizen
print(pfad.suffix) # .txt
print(pfad.parent) # daten/projekte
# Pruefen, ob Datei/Ordner existiert
print(pfad.exists()) # True oder False
print(pfad.is_file()) # True oder False
print(pfad.is_dir()) # True oder False
Dateien mit pathlib lesen und schreiben
from pathlib import Path
pfad = Path("notizen.txt")
# Schreiben (ueberschreibt)
pfad.write_text("Meine erste Notiz\n", encoding="utf-8")
# Lesen
inhalt = pfad.read_text(encoding="utf-8")
print(inhalt)
# Ordner erstellen (auch verschachtelt)
ordner = Path("daten") / "backup"
ordner.mkdir(parents=True, exist_ok=True)
Dateien in einem Ordner auflisten
from pathlib import Path
ordner = Path(".") # Aktueller Ordner
# Alle .py-Dateien finden
for py_datei in ordner.glob("*.py"):
print(py_datei.name)
# Rekursiv in Unterordnern suchen
for py_datei in ordner.rglob("*.py"):
print(py_datei)
Praxis: Notizen-App
Lass uns eine kleine Notizen-App bauen, die Notizen in einer Datei speichert:
import json
from pathlib import Path
from datetime import datetime
NOTIZEN_DATEI = Path("notizen.json")
def notizen_laden():
"""Laedt Notizen aus der JSON-Datei."""
if NOTIZEN_DATEI.exists():
with open(NOTIZEN_DATEI, "r", encoding="utf-8") as datei:
return json.load(datei)
return []
def notizen_speichern(notizen):
"""Speichert Notizen in der JSON-Datei."""
with open(NOTIZEN_DATEI, "w", encoding="utf-8") as datei:
json.dump(notizen, datei, indent=2, ensure_ascii=False)
def notiz_hinzufuegen(text):
"""Fuegt eine neue Notiz hinzu."""
notizen = notizen_laden()
neue_notiz = {
"text": text,
"erstellt": datetime.now().strftime("%Y-%m-%d %H:%M"),
"erledigt": False
}
notizen.append(neue_notiz)
notizen_speichern(notizen)
print(f"Notiz hinzugefuegt: {text}")
def notizen_anzeigen():
"""Zeigt alle Notizen an."""
notizen = notizen_laden()
if not notizen:
print("Keine Notizen vorhanden.")
return
for i, notiz in enumerate(notizen, 1):
status = "x" if notiz["erledigt"] else " "
print(f" [{status}] {i}. {notiz['text']} ({notiz['erstellt']})")
# Ausprobieren
notiz_hinzufuegen("Python-Tutorial durcharbeiten")
notiz_hinzufuegen("Einkaufen gehen")
notizen_anzeigen()
Praxis: Config-Datei lesen
import json
from pathlib import Path
STANDARD_CONFIG = {
"app_name": "MeineApp",
"version": "1.0",
"debug": False,
"max_eintraege": 100,
"farben": {
"hintergrund": "#FFFFFF",
"text": "#333333"
}
}
def config_laden(pfad="config.json"):
"""Laedt die Konfiguration oder erstellt eine Standardkonfiguration."""
config_pfad = Path(pfad)
if config_pfad.exists():
with open(config_pfad, "r", encoding="utf-8") as datei:
return json.load(datei)
else:
print("Keine Config gefunden -- erstelle Standardkonfiguration...")
with open(config_pfad, "w", encoding="utf-8") as datei:
json.dump(STANDARD_CONFIG, datei, indent=4, ensure_ascii=False)
return STANDARD_CONFIG.copy()
config = config_laden()
print(f"App: {config['app_name']} v{config['version']}")
print(f"Debug-Modus: {config['debug']}")
Uebungen
Uebung 1: Einkaufsliste
Schreibe ein Programm, das eine Einkaufsliste in einer Textdatei verwaltet. Es soll Artikel hinzufuegen, alle anzeigen und die Liste loeschen koennen.
def artikel_hinzufuegen(artikel):
with open("einkaufsliste.txt", "a", encoding="utf-8") as datei:
datei.write(artikel + "\n")
print(f"'{artikel}' hinzugefuegt!")
def liste_anzeigen():
try:
with open("einkaufsliste.txt", "r", encoding="utf-8") as datei:
zeilen = datei.readlines()
if not zeilen:
print("Die Liste ist leer.")
return
print("--- Einkaufsliste ---")
for i, zeile in enumerate(zeilen, 1):
print(f" {i}. {zeile.strip()}")
except FileNotFoundError:
print("Noch keine Liste vorhanden.")
def liste_loeschen():
with open("einkaufsliste.txt", "w", encoding="utf-8") as datei:
pass # Leere Datei
print("Liste geloescht!")
# Test
artikel_hinzufuegen("Milch")
artikel_hinzufuegen("Brot")
artikel_hinzufuegen("Kaese")
liste_anzeigen()
Uebung 2: Woerterzaehler
Lies eine Textdatei ein und zaehle, wie oft jedes Wort vorkommt:
from collections import Counter
def woerter_zaehlen(dateipfad):
with open(dateipfad, "r", encoding="utf-8") as datei:
text = datei.read().lower()
woerter = text.split()
zaehler = Counter(woerter)
print("Die 10 haeufigsten Woerter:")
for wort, anzahl in zaehler.most_common(10):
print(f" {wort}: {anzahl}x")
# woerter_zaehlen("mein_text.txt")
Uebung 3: Kontaktbuch als JSON
Erstelle ein Kontaktbuch, das Namen, Telefonnummern und E-Mail-Adressen in einer JSON-Datei speichert:
import json
from pathlib import Path
KONTAKTE_DATEI = Path("kontakte.json")
def kontakte_laden():
if KONTAKTE_DATEI.exists():
return json.loads(KONTAKTE_DATEI.read_text(encoding="utf-8"))
return {}
def kontakt_speichern(name, telefon, email):
kontakte = kontakte_laden()
kontakte[name] = {"telefon": telefon, "email": email}
KONTAKTE_DATEI.write_text(
json.dumps(kontakte, indent=2, ensure_ascii=False),
encoding="utf-8"
)
print(f"Kontakt '{name}' gespeichert!")
def kontakt_suchen(name):
kontakte = kontakte_laden()
if name in kontakte:
k = kontakte[name]
print(f"{name}: {k['telefon']} | {k['email']}")
else:
print(f"Kontakt '{name}' nicht gefunden.")
# Test
kontakt_speichern("Anna", "0170-1234567", "anna@example.com")
kontakt_speichern("Ben", "0171-9876543", "ben@example.com")
kontakt_suchen("Anna")
Pro-Tipp: Fehlerbehandlung bei Dateioperationen
Dateien koennen fehlen, Berechtigungen koennen falsch sein, die Festplatte kann voll sein. Verwende immer Try-Except bei Dateioperationen in echten Programmen:
from pathlib import Path
def sichere_datei_lesen(pfad):
try:
with open(pfad, "r", encoding="utf-8") as datei:
return datei.read()
except FileNotFoundError:
print(f"Datei '{pfad}' nicht gefunden!")
return None
except PermissionError:
print(f"Keine Berechtigung fuer '{pfad}'!")
return None
except UnicodeDecodeError:
print(f"Datei '{pfad}' hat ein unbekanntes Encoding!")
return None
Und noch ein goldener Tipp: Nutze pathlib.Path.exists(), um vorher zu pruefen, ob eine Datei existiert — aber verlasse dich nicht allein darauf, denn zwischen Pruefung und Zugriff kann sich der Zustand aendern (Race Condition). Die Kombination aus Pruefung und Try-Except ist die sicherste Variante.