mitmario.dev

Synthese: Der Kontoauszug, erste Fassung

Python Sandbox 4 Min Lesezeit 3 BeispieleLektion 6 von 8

Ein Werkzeug, das einen Kontoauszug einliest und zeigt, wofür das Geld draufgegangen ist, hat dieser Kurs von Anfang an versprochen. Hier ist die erste Fassung. Es braucht nichts, was nicht in diesem Abschnitt oder davor vorkam. Trotzdem ist es ein Programm, das du nächsten Monat mit deinem eigenen Auszug benutzen kannst. Später im Kurs bekommt es Klassen, Tests und Schalter beim Start, aber rechnen kann es ab heute.

Erst der Plan

Wie beim Aufräumer steht am Anfang eine Liste.

  1. Den Export der Bank einlesen und Beträge und Daten in Werte verwandeln, mit denen man rechnen kann.
  2. Jede Ausgabe über Stichwörter im Empfänger einer Kategorie zuordnen. Einnahmen wie das Gehalt gehören nicht dazu, die Frage ist ja, wohin das Geld ging.
  3. Je Kategorie zusammenzählen und die größte zuerst stellen.
  4. Drei Ausgaben für drei Leser. Eine Übersicht im Terminal für dich, bericht.csv für die Tabellenkalkulation und bericht.json, damit ein Programm nächsten Monat vergleichen kann.
  5. Das Ganze in Teile aufteilen, die je eine Sache tun.

Was die Bank liefert

Was die Bank liefert
import csv

with open("kontoauszug.csv", encoding="utf-8-sig", newline="") as datei:
    leser = csv.DictReader(datei, delimiter=";")
    print(leser.fieldnames)
    for buchung in leser:
        print(buchung["Buchungstag"], buchung["Empfänger"], buchung["Betrag"])

Fast jede Bank bietet im Online-Banking einen Export als CSV an, und die Dateien sehen sich ähnlich. Semikolon, Beträge mit Komma, ein Minus vor jeder Ausgabe. Nur die Spalten heißen bei jeder Bank etwas anders, und meistens sind es mehr, als man braucht.

Hier gibt es eine Wertstellung (der Tag, ab dem das Geld zählt) und eine Währung, und beide braucht das Werkzeug nicht. Mit DictReader stören sie auch nicht. Du fragst einfach nach den Spalten, die du willst. Und wenn bei der nächsten Bank eine Spalte dazukommt, ändert sich nichts.

Die Empfänger stehen in Großbuchstaben da, so wie viele Banken sie schreiben. Für die Regeln ist das gleich wichtig.

Regeln für Kategorien

Welche Kategorie zu welcher Buchung gehört, steht in einem Dictionary, links das Stichwort und rechts die Kategorie. Gesucht wird das Stichwort im Empfänger, und zwar auf beiden Seiten klein geschrieben, so wie beim Suchwort im Postfach. Sonst fände "supermarkt" nichts in SUPERMARKT SONNENBLICK. Was zu keiner Regel passt, ist Sonstiges. Daran sieht man, dass eine Regel fehlt.

Gefunden und weitergesucht
# Die Tankstelle steht vor dem Supermarkt: Tanken ist Mobilität, auch an
# einer Tankstelle, die zu einem Supermarkt gehört.
REGELN = {
    "tankstelle": "Mobilität",
    "supermarkt": "Lebensmittel",
    "stadtwerke": "Wohnen",
}


def kategorie(empfaenger):
    """Gibt die Kategorie für einen Empfänger zurück, nach REGELN."""
    empfaenger = empfaenger.lower()
    gefunden = "Sonstiges"
    for stichwort, name in REGELN.items():
        if stichwort in empfaenger:
            gefunden = name
    return gefunden


print(kategorie("STADTWERKE LINDENAU"))
print(kategorie("Supermarkt Sonnenblick"))
print(kategorie("KINO LICHTSPIEL"))
print(kategorie("SUPERMARKT-TANKSTELLE NORD"))

Schwierig wird es bei einem Empfänger, auf den zwei Regeln passen. Die Tankstelle am Supermarkt soll Mobilität sein, und deshalb steht ihre Regel vorn. Mit dieser Fassung von kategorie kommt trotzdem Lebensmittel heraus. Jeder Treffer wird gemerkt, und dann wird weitergesucht. So zählt am Ende die letzte passende Regel und nicht die erste.

Damit die Reihenfolge im Dictionary etwas bedeutet, muss die Suche beim ersten Treffer aufhören. Dafür reicht ein return genau an der Stelle, an der etwas gefunden wird, weil es die Funktion samt Schleife beendet. Erst wenn die Schleife ganz durch ist, bleibt Sonstiges.

Drei Leser, drei Formen

Ein Betrag, drei Leser
from decimal import Decimal

wohnen = Decimal("1204.00")
print(f"Im Terminal: {wohnen:.2f} Euro")
print("Für Excel:", f"{wohnen:.2f}".replace(".", ","))
print("Für JSON:", str(wohnen))

Gerechnet wird mit Decimal, und derselbe Betrag kommt dreimal hinaus, jedes Mal anders. Im Terminal liest ihn ein Mensch, da reicht :.2f. In bericht.csv liest ihn Excel, also mit Komma. Und in bericht.json liest ihn nächsten Monat ein Programm. Dort steht er als Text aus str(), und Decimal(...) macht daraus wieder genau den Betrag.

JSON würde zwar auch eine Kommazahl nehmen. Dann wäre aber die ganze Mühe mit Decimal an der letzten Stelle umsonst gewesen.

Zu Hause benutzen

Mit dieser Lektion hast du alles beisammen, was man für den Alltag mit Dateien und Tabellen braucht, und dazu ein Werkzeug, das auf deinem Rechner läuft. Wie man Python dort startet, steht in Lektion 11.1.

Den Export deiner Bank legst du als kontoauszug.csv in den Ordner des Programms. Dann ersetzt du die Spaltennamen durch die deiner Bank und die Regeln durch deine eigenen Empfänger. Bricht das Einlesen mit einem UnicodeDecodeError ab, ist der Export nicht in UTF-8 geschrieben, sondern meistens in der alten Windows-Kodierung. Dann heißt es encoding="cp1252" statt utf-8-sig.

Als Erstes lohnt sich ein Blick auf das, was unter Sonstiges landet. Daran siehst du die Regeln, die noch fehlen.

Was die Aufgabe will

Der Kontoauszug eines Monats. Die Regeln stehen schon in main.py, und zahl_aus_text und datum_aus_text liegen fertig in werkzeuge.py. Zu bauen ist das Werkzeug aus dem Plan, also die Kategorie zu jedem Empfänger, die Summen je Kategorie und die drei Ausgaben.

Zum Mitnehmen

Das Werkzeug liest den CSV-Export der Bank und ordnet jede Ausgabe über Stichwörter im Empfänger einer Kategorie zu, wobei die erste passende Regel gilt. Dann zählt es je Kategorie zusammen. Am Ende gibt es drei Ergebnisse, die Übersicht im Terminal, bericht.csv für Excel und bericht.json für den Vergleich im nächsten Monat.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

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 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, dein Code läuft auf einem Server

    Öffnet sich mit dem Basis Konto.