4.6.6 Fehler vermeiden: prüfen und absichern

In Python, und besonders bei der Programmierung von Mikrocontrollern, kann schon ein kleiner Fehler das ganze Programm stoppen oder zu unvorhersehbarem Verhalten führen. Deshalb ist es wichtig, Daten vor der Weiterverarbeitung zu überprüfen oder Fehler gezielt abzufangen.

🧱 Was ist ein Fehler?

In der Programmierung unterscheidet man:

  • Syntaxfehler: Der Code ist formal falsch. → Das Programm startet nicht: z. B. print("Hallo → fehlende Klammer.
  • Laufzeitfehler: Ein Fehler passiert während der Ausführung. Beispiel Division durch 0: meinWert = 10 / 0.
  • Logischer Fehler: Der Code läuft – macht aber nicht, was er soll, z. B. TypeError: 3 + "5".

🔍 Datentypen prüfen mit isinstance()

Oft muss geprüft werden, ob ein Wert vom richtigen Typ ist – z. B. eine Zahl. Dafür verwenden wir isinstance().

1
2
3
4
5
6
7
8
9
zahl = 42.5

if isinstance(zahl, int):
    print(f"{zahl} ist ein Integer.")
else:
    print(f"{zahl} ist kein Integer.")

# Umwandeln in eine ganze Zahl
zahl = int(zahl)

🧰 Fehler vermeiden mit if

Bevor ein Fehler entsteht, können wir durch eine if-Prüfung vorbeugen:

1
2
3
4
5
6
7
8
def addiere(a, b):
    if isinstance(a, int) and isinstance(b, int):
        return a + b
    else:
        print("Nur ganze Zahlen erlaubt!")

print(addiere(3, 4))      # OK
print(addiere("3", 4))    # Fehlermeldung

🛑 Fehler abfangen mit try / except

Manchmal ist eine Prüfung vorher schwierig. Dann kann man Fehler abfangen, wenn sie auftreten.

Funktionsweise

  • try: Der Code, der in den try-Block geschrieben wird, ist der Teil des Programms, der möglicherweise einen Fehler verursachen könnte. Python versucht, diesen Code auszuführen.

    In diesem Block wird der Hauptteil des Codes ausgeführt, der den Lux-Wert vom Lichtsensor liest und ihn auf dem OLED-Display anzeigt. Dieser Code wird in einer Schleife ausgeführt, um kontinuierlich den Helligkeitswert zu aktualisieren.

  • except: Falls im try-Block ein Fehler auftritt, wird der except-Block ausgeführt. Hier kann definiert werden, was im Fehlerfall passieren soll, z.B. eine Fehlermeldung ausgeben oder das Programm in einen sicheren Zustand versetzen.

    Falls während der Ausführung des Codes im try-Block ein Fehler auftritt (z.B. ein Problem mit der Verbindung zum Sensor oder Display), wird der except-Block aktiviert. Das Programm beendet sich damit kontrolliert. In diesem Fall wird nur eine einfache Nachricht ausgegeben, damit das Programm an dieser Stelle nicht zu lang wird. Anstelle einer einfachen Ausgabe könnte auch ein Eintrag in eine Log-Datei geschrieben werden.

1
2
3
4
try:
    z = 10 / 0
except ZeroDivisionError:
    print("Durch 0 teilen geht nicht!")

Das Programm stürzt jetzt nicht ab – es wird eine Meldung ausgegeben.

Wichtig: Wann if, wann try

🧠 Merksatz:

  • Verwende if, um vorher sicherzustellen, dass alles korrekt ist (z. B. Benutzereingaben).
  • Verwende try, um Fehler beim Ausführen abzufangen (z. B. Datei nicht vorhanden, falscher Pin).

💡 Praxisbeispiel mit Absicherung

Hier ein Beispiel, zuerst nicht abgesichert und dann abgesichert.

# LED-Steuerung ohne Fehlerprüfung
# J. Thomaschewski, 29.07.2025

from machine import Pin
from time import sleep

class LedBlinker:
    def __init__(self, pinValue):
        self.led = Pin(pinValue, Pin.OUT)

    def blink(self, times, delay):
        for _ in range(times):
            self.led.on()
            sleep(delay)
            self.led.off()
            sleep(delay)

# Hauptprogramm
led = LedBlinker('LED')
led.blink(5, 0.5)
Hieran lässt sich noch gut erkennen, was das Programm macht.

# LED-Steuerung mit Schutz und privaten Attributen
# J. Thomaschewski, 29.07.2025

from machine import Pin
from time import sleep

class LedBlinker:
    def __init__(self, pinValue):
        try:
            if isinstance(pinValue, int):
                self.__led = Pin(pinValue, Pin.OUT)
            elif pinValue == 'LED':
                self.__led = Pin('LED', Pin.OUT)
            else:
                raise TypeError("pinValue muss int oder 'LED' sein.")
        except Exception as e:
            print(f"Fehler bei der Initialisierung: {e}")
            self.__led = None

    def blink(self, times, delay):
        if self.__led is None:
            print("LED wurde nicht korrekt initialisiert.")
            return
        try:
            if not isinstance(times, int):
                raise TypeError("times muss int sein.")
            if not isinstance(delay, (int, float)):
                raise TypeError("delay muss Zahl sein.")
            for _ in range(times):
                self.__led.on()
                sleep(delay)
                self.__led.off()
                sleep(delay)
        except Exception as e:
            print(f"Fehler beim Blinken: {e}")

# Hauptprogramm
led = LedBlinker('LED')
led.blink(5, 0.5)

# led.blink("Hallo", 0.5)  # Probiere dies für einen Fehlerfall

Und plötzlich haben wir sehr viel Sourcecode, aber auch einen sehr guten Sourcecode. Problem: man braucht wirklich Übung, um zu erkennen, was gemacht wird.


📦 Zusammenfassung

Wichtige Techniken zur Fehlerbehandlung

  • isinstance(x, typ): Überprüft den Typ einer Variable.
  • int(x): Wandelt x in eine Ganzzahl um (Fehler möglich!).
  • try / except: Fängt Fehler ab, ohne das Programm zu beenden.
  • Klassenmethoden absichern: Besonders wichtig bei Eingaben oder GPIO-Zugriff.