Abschnitt 19 · Lektion 1
Der Plan
Die erste Fassung des Kontoauszugs reicht für einen Monat. Sie stammt aus Abschnitt 12, liest ein, ordnet jede Ausgabe einer Kategorie zu und zählt zusammen. Aber die Regeln stehen im Code. Ein Export, der anders anfängt oder anders kodiert ist, bringt sie aus dem Tritt. Und ob sie nach der nächsten Änderung noch richtig rechnet, sagt einem niemand.
In diesem Abschnitt wird daraus ein Werkzeug, das man wirklich jeden Monat benutzt. Neuen Stoff gibt es kaum. Alles, was du dafür brauchst, kam im Kurs schon einmal vor, nur muss es diesmal zusammenpassen.
Und wie beim Spritkostenrechner früh im Kurs steht am Anfang kein Code, sondern ein Zettel.
Was hineingeht
Umsätze Girokonto;DE12 3456 7890 1234 5678 90
Zeitraum;01.08.2026 bis 31.10.2026
Kontostand am 31.10.2026;3.214,55 EUR
Buchungstag;Wertstellung;Empfänger;Verwendungszweck;Betrag;Währung
30.10.2026;30.10.2026;STADTWERKE LINDENAU;Abschlag Strom 10/2026;-91,00;EUR
28.10.2026;28.10.2026;DRUCKEREI KRANICH GMBH;Gehalt Oktober;2.580,00;EUR
27.10.2026;27.10.2026;BUCHHANDLUNG SEITENWEISE;Kartenzahlung;-31,90;EUR
24.10.2026;26.10.2026;SUPERMARKT SONNENBLICK FIL. 12;Kartenzahlung;-71,36;EUR
20.10.2026;20.10.2026;BÄCKEREI KRUME;Kartenzahlung;-6,20;EUR
15.10.2026;15.10.2026;HAUSVERWALTUNG AHORN;Miete November;-1.120,00;EUR
12.10.2026;12.10.2026;HAUSVERWALTUNG AHORN;Erstattung Nebenkosten 2025;86,40;EUR
06.10.2026;06.10.2026;APOTHEKE AM MARKT;Kartenzahlung;-18,95;EUR
05.10.2026;05.10.2026;FITNESSSTUDIO KRAFTWERK;Beitrag Oktober;-39,00;EUR
02.10.2026;02.10.2026;SUPERMARKT SONNENBLICK FIL. 12;Bargeldauszahlung;-50,00;EUR
01.10.2026;01.10.2026;VERKEHRSBETRIEBE LINDENAU;Monatskarte;-58,00;EUR
30.09.2026;30.09.2026;STADTWERKE LINDENAU;Abschlag Strom 09/2026;-84,00;EUR
29.09.2026;29.09.2026;SUPERMARKT SONNENBLICK FIL. 12;Kartenzahlung;-63,47;EUR
28.09.2026;28.09.2026;DRUCKEREI KRANICH GMBH;Gehalt September;2.580,00;EUR
22.09.2026;22.09.2026;DROGERIE IM BAHNHOF;Kartenzahlung;-12,95;EUR
15.09.2026;15.09.2026;HAUSVERWALTUNG AHORN;Miete Oktober;-1.120,00;EUR
12.09.2026;14.09.2026;KINO LICHTSPIEL;Kartenzahlung;-24,00;EUR
10.09.2026;10.09.2026;BÄCKEREI KRUME;Kartenzahlung;-8,40;EUR
03.09.2026;03.09.2026;OLE BERGER;Anteil Konzertkarten;45,00;EUR
02.09.2026;02.09.2026;SUPERMARKT SONNENBLICK FIL. 12;Kartenzahlung;-52,18;EUR
01.09.2026;01.09.2026;VERKEHRSBETRIEBE LINDENAU;Monatskarte;-58,00;EUR
31.08.2026;31.08.2026;STADTWERKE LINDENAU;Abschlag Strom 08/2026;-84,00;EUR
28.08.2026;28.08.2026;DRUCKEREI KRANICH GMBH;Gehalt August;2.580,00;EUR
25.08.2026;25.08.2026;SUPERMARKT SONNENBLICK FIL. 12;Kartenzahlung;-58,12;EUR
19.08.2026;19.08.2026;BUCHHANDLUNG SEITENWEISE;Geschenkgutschein 25 €;-25,00;EUR
14.08.2026;14.08.2026;HAUSVERWALTUNG AHORN;Miete September;-1.120,00;EUR
10.08.2026;10.08.2026;KIOSK AM MARKT;Kartenzahlung;-4,50;EUR
03.08.2026;03.08.2026;VERKEHRSBETRIEBE LINDENAU;Monatskarte;-58,00;EUR
01.08.2026;03.08.2026;BÄCKEREI KRUME;Kartenzahlung;-7,80;EUR from pathlib import Path
zeilen = Path("kontoauszug.csv").read_text(encoding="utf-8").splitlines()
print(len(zeilen), "Zeilen, die ersten acht:")
for nummer, zeile in enumerate(zeilen[:8], start=1):
print(nummer, zeile) Hinein geht der Export aus dem Online-Banking, drei Monate eines Girokontos. Schon in den ersten Zeilen stecken zwei Dinge, die die erste Fassung nicht kannte.
Die Zeile mit den Spaltennamen steht nicht oben, sondern in Zeile 5. Davor stehen das Konto, der Zeitraum und der Kontostand, und dann kommt eine leere Zeile. Viele Banken machen das so, jede ein bisschen anders.
Außerdem steht neben dem Empfänger ein Verwendungszweck, und bei manchen Buchungen erfährt man nur dort, worum es geht. Beim Gehalt steht in der Spalte Empfänger die Firma, die es überweist. Dass es das „Gehalt Oktober“ ist, steht erst im Verwendungszweck.
Was man der Datei nicht ansieht, ist ihre Kodierung. Diese hier ist in UTF-8 geschrieben, wie alle Dateien im Kurs. Manche Banken schreiben ihren Export aber in der alten Windows-Kodierung, und dann bricht das Lesen als UTF-8 schon beim ersten Umlaut ab, dem ä in „Umsätze“ ganz oben. Darum geht es in der nächsten Lektion.
Was herauskommen soll
Am Ende steht ein Aufruf, wie man ihn von Werkzeugen kennt:
python main.py kontoauszug.csv --monat 2026-09. Im Terminal erscheint dann eine Übersicht über den
Monat. Oben eine Tabelle mit den Ausgaben je Kategorie, die größte zuerst, darunter, was hereinkam,
was hinausging und was bleibt.
Daneben entsteht eine Datei für die Tabellenkalkulation, in der jede Buchung des Monats mit ihrer Kategorie steht. Wenn du dort nachsehen willst, welche Ausgaben unter Lebensmittel gelandet sind, filterst du eine Spalte und musst nichts mehr von Hand abtippen.
Was nicht herauskommen soll, gehört auch auf den Zettel. In den Export wird nichts zurückgeschrieben, keine Bank wird im Netz gefragt, und zwischen zwei Aufrufen merkt sich das Werkzeug nichts. Jeder Monat ist ein neuer Aufruf mit einer neuen Datei.
Die Teile
Zwischen Datei und Übersicht liegen vier Schritte, und jeder bekommt ein eigenes Modul:
einlesen.pymacht aus der Datei eine Liste von Buchungen, mit Datum alsdateund Betrag alsDecimal, egal in welcher der beiden Kodierungen sie kommt.kategorien.pyliest die Regeln ausregeln.csvund gibt jeder Buchung ihre Kategorie.bericht.pyfasst einen Monat zusammen und gibt die Übersicht als Text zurück.test_auswerter.pyprüft die drei Teile mit pytest, damit eine Änderung an den Regeln nicht still etwas anderes kaputt macht.
main.py setzt alles zusammen und liest, was beim Aufruf dahintersteht. Die Reihenfolge ist die, in
der die Daten fließen. Jeder Teil braucht nur die Teile davor, und keiner muss wissen, wie ein
anderer innen aussieht. Früher stand dieselbe Aufteilung in den Funktionen einer Datei. Diesmal
steht sie in Modulen.
Ein Gerüst, das schon läuft
from dataclasses import dataclass
from datetime import date
from decimal import Decimal
@dataclass
class Buchung:
datum: date
empfaenger: str
zweck: str
betrag: Decimal
kategorie: str = "Sonstiges"
def lies_kontoauszug(pfad):
"""Liest den Export der Bank und gibt (buchungen, kodierung) zurück."""
# Attrappe bis Lektion 19.2: zwei feste Buchungen statt der Datei.
buchungen = [
Buchung(date(2026, 9, 30), "STADTWERKE LINDENAU", "Abschlag Strom 09/2026", Decimal("-84.00")),
Buchung(date(2026, 9, 28), "DRUCKEREI KRANICH GMBH", "Gehalt September", Decimal("2580.00")),
]
return buchungen, "utf-8" def lies_regeln(pfad):
"""Liest die Regeln aus der Datei: Stichwort zu Kategorie."""
# Attrappe bis Lektion 19.3: keine Regeln.
return {}
def kategorisiere(buchung, regeln):
"""Gibt die Kategorie der Buchung zurück, nach den Regeln."""
# Attrappe bis Lektion 19.3: alles ist Sonstiges.
return "Sonstiges" def uebersicht(buchungen, monat):
"""Gibt die Übersicht über einen Monat als Text zurück."""
# Attrappe bis Lektion 19.4: nur die Zahl der Buchungen.
return f"Übersicht {monat}: {len(buchungen)} Buchungen, die Tabelle kommt noch" from bericht import uebersicht
from einlesen import lies_kontoauszug
from kategorien import kategorisiere, lies_regeln
# So soll es am Ende aussehen, nach Lektion 19.6:
# $ python main.py kontoauszug.csv --monat 2026-09
# kontoauszug.csv: 29 Buchungen, utf-8
# Übersicht 2026-09: 10 Buchungen
# (eine Tabelle mit den Ausgaben je Kategorie)
# Einnahmen: 2.625,00 €
# Ausgaben: 1.423,00 €
# Bleibt: 1.202,00 €
# Bericht: bericht-2026-09.csv
def main():
buchungen, kodierung = lies_kontoauszug("kontoauszug.csv")
regeln = lies_regeln("regeln.csv")
for buchung in buchungen:
buchung.kategorie = kategorisiere(buchung, regeln)
print(f"kontoauszug.csv: {len(buchungen)} Buchungen, {kodierung}")
print(uebersicht(buchungen, "2026-09"))
if __name__ == "__main__":
main() Das Werkzeug kann schon laufen, bevor eine einzige Funktion etwas Echtes tut. Jede Funktion steht
mit Namen, Parametern und Docstring da und gibt etwas Festes zurück. Das ist eine Attrappe, so wie
die Pappfernseher, die ein Möbelhaus in die Schrankwand stellt. lies_kontoauszug liefert zwei
Buchungen, die gar nicht aus der Datei kommen, kategorisiere sagt zu allem Sonstiges, und
uebersicht zählt nur.
Das sieht nach Spielerei aus. Tatsächlich ist es der wichtigste Teil des Plans, weil im Gerüst
festgelegt ist, was zwischen den Teilen hin und her geht. lies_kontoauszug gibt die Buchungen und
die Kodierung zusammen zurück. kategorisiere bekommt eine Buchung und die Regeln und gibt den
Namen einer Kategorie zurück. Und uebersicht gibt einen Text zurück, statt ihn auszugeben.
Wenn das stimmt, lässt sich jede Attrappe einzeln gegen echten Code tauschen, und main.py merkt
davon nichts. Ganz oben in main.py steht im Kommentar, wie es am Ende aussehen soll.
Warum der Plan schon die halbe Arbeit ist
Ein paar Entscheidungen sind in diesem Gerüst schon gefallen, und für jede gibt es einen Grund aus
einem früheren Abschnitt. Das Datum ist ein date, weil ein Datum als Text falsch sortiert wird
(Lektion 8.7) und weil man aus einem date den Monat holen kann. Der Betrag ist ein Decimal, weil
es um Geld geht (Lektion 10.5). Die Regeln stehen in einer Datei, weil man sie öfter ändert als den
Code. Und die Übersicht kommt als Text zurück, weil sich ein Text in einem Test prüfen lässt, eine
Ausgabe auf dem Bildschirm dagegen nur schwer.
Jede dieser Entscheidungen kostet jetzt einen Satz. Nach drei Wochen Bauzeit kostet jede einen Nachmittag, weil dann schon Code an der alten Form hängt. Der Plan passt auf eine Seite und ist trotzdem die halbe Arbeit, denn was danach noch fehlt, sind nur noch Lücken, bei denen schon klar ist, was hineingehört.
Ein Modul je Aufgabe
Die Attrappen werden eine nach der anderen gegen den echten Teil getauscht, und in jeder Aufgabe
arbeitest du in genau einem Modul. Die Teile davor liegen im Dateibaum unter Dateien, so wie sie
nach der Lektion davor aussehen, und main.py wächst mit. Wie weit das Werkzeug schon ist, siehst
du in jeder Lektion am Befehl mit python main.py in der Befehlsleiste.
Zum Mitnehmen
Am Anfang eines Werkzeugs steht ein Zettel mit dem, was hineingeht, dem, was herauskommen soll, und den Teilen dazwischen. Jeder Teil wird ein Modul mit einer Aufgabe, und Namen, Parameter und Rückgaben der Funktionen liegen fest, bevor auch nur eine davon etwas Echtes tut. Gebaut wird in der Reihenfolge vom Export zur Übersicht, und bis dahin halten Attrappen das Gerüst am Laufen.
Jetzt du
Basis Konto, kostenlosIm Editor änderst du die Beispiele dieser Lektion und lässt sie gleich laufen. So merkst du am schnellsten, ob es sitzt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 2 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.