Effektives Debugging mit der Python Assert-Anweisung

Sind Sie ein Programmierer? Wenn ja, ist das Debuggen eine unverzichtbare Fähigkeit, unabhängig davon, in welcher Programmiersprache Sie arbeiten. In diesem Artikel erfahren Sie, wie Sie die assert-Anweisung in Python effektiv zum Debuggen nutzen können.

Bei der Entwicklung eines Projekts definieren Sie verschiedene Module, darunter Funktionen, Klassendefinitionen und mehr. Dabei stoßen Sie wahrscheinlich auf Fehler oder unerwartete Ergebnisse, die auf Implementierungsfehler zurückzuführen sind. Hierbei sind assert-Anweisungen sehr hilfreich.

In diesem Tutorial lernen Sie die Syntax für die Verwendung der assert-Anweisung kennen. Wir betrachten anschließend Codebeispiele, um die Anwendung in der Praxis zu sehen. Außerdem werden wir uns ansehen, was AssertionError-Fehler sind und wie wir diese einsetzen können, um Fehler im Code während der Entwicklungsphase zu beheben.

Legen wir los!

Die Verwendung der assert-Anweisung in Python

Wir werden zuerst die Syntax der assert-Anweisung erlernen und dann mit der Erstellung einiger praktischer Beispiele fortfahren.

Syntax der assert-Anweisung

Beginnen wir mit der Syntax, um die assert-Anweisung in Python zu verwenden:

assert ausdruck, meldung

Hierbei gilt:

  • ausdruck ist ein beliebiger gültiger Python-Ausdruck, der ausgewertet werden soll. Dies kann eine Bedingung für den Wert einer Variable, den Wahrheitswert einer Variable oder den Rückgabewert einer Funktion sein.
  • Solange der ausdruck den Wert True ergibt, gibt die assert-Anweisung keinen Fehler aus und hat keine Rückgabe. Dies zeigt an, dass das Programm wie erwartet funktioniert.
  • Wenn der ausdruck nicht mehr True ist, wird eine AssertionError-Ausnahme ausgelöst.
  • meldung ist ein optionaler String. Sie können eine Nachricht angeben, die in der Rückverfolgung angezeigt wird, wenn eine AssertionError-Ausnahme auftritt.

Lassen Sie uns nun einige Beispiele programmieren, in denen die assert-Anweisung uns dabei unterstützen kann, saubereren und fehlerfreien Code zu schreiben.

Die in diesem Tutorial verwendeten Codebeispiele sind in diesem GitHub-Gist zu finden.

Beispiele für die assert-Anweisung in Python

Betrachten Sie folgendes Beispiel: Angenommen, Sie haben in Ihrem Code eine Rabattvariable. Ihr Wert soll jedoch stets kleiner oder gleich einem max_discount sein.

Um zu überprüfen, ob Sie die Rabattvariable nicht versehentlich auf einen falschen Wert gesetzt haben, können Sie eine Assertion hinzufügen. Der zu überprüfende Ausdruck lautet dann: discount <= max_discount.

>>> max_discount = 50
>>> discount = 20
>>> assert discount <= max_discount

Hier ist discount (20) kleiner als max_discount (50). Die assert-Anweisung löst daher keinen Fehler aus.

Die AssertionError-Ausnahme

Wenn die Rabattvariable auf einen Wert größer als max_discount gesetzt wird, wird eine AssertionError-Ausnahme ausgelöst.

>>> discount = 75
>>> assert discount <= max_discount
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

Wir wissen, dass wir mit der assert-Anweisung auch eine optionale Nachricht angeben können.

Fügen wir also eine aussagekräftigere Diagnoseinformation hinzu. Verwenden wir dafür einen Python-F-String, der auch die Werte von discount und max_discount enthält.

>>> assert discount <= max_discount, f"Der Rabatt sollte maximal {max_discount} betragen; aktueller Rabatt: {discount}"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: Der Rabatt sollte maximal 50 betragen; aktueller Rabatt: 75

Wie in der obigen Ausgabe zu sehen ist, enthält die Ausnahme AssertionError jetzt die Werte der Variablen discount und max_discount.

Debuggen und Testen von Python-Funktionen mit assert

Beim Definieren von Funktionen können Sie manchmal versehentlich Fehler (logische Fehler) einführen, die verhindern, dass Ihre Funktion wie beabsichtigt funktioniert.

Nehmen wir ein Beispiel: Angenommen, es gibt einen Test in einer Klasse und die Schüler haben die Möglichkeit, eine Bonusfrage zu beantworten. Jeder Schüler, der die Bonusfrage versucht, erhält 10 zusätzliche Punkte im Test. 😄

Betrachten Sie die folgende Funktion get_final_score:

  • Sie nimmt eine aktuelle Punktzahl und einen booleschen Wert für den Bonus an.
  • Wenn ein Schüler die Bonusfrage beantwortet hat, ist der boolesche Wert bonus True, und er erhält 10 Punkte mehr als seine aktuelle Punktzahl.
  • Die Funktion gibt dann die Endpunktzahl zurück.
def get_final_score(score,bonus):
    if bonus:
        score += 10
    return score

Führen wir einige Aufrufe der Funktion aus. Wir sehen, dass bei Ergebnissen von 34 und 40, mit bonus auf True bzw. False gesetzt, die Endergebnisse 44 bzw. 40 sind.

print(get_final_score(34,True))
# 44
print(get_final_score(40,False))
# 40

Die maximale Punktzahl für den Test beträgt jedoch beispielsweise 50. Wenn also ein Schüler 49 Punkte erzielt und auch die Bonusfrage beantwortet hat, berechnet die Funktion get_final_score die Endpunktzahl 59.

print(get_final_score(49,True))
# 59

Technisch ist dies möglich. Nehmen wir jedoch an, dass ein Schüler nicht mehr als die maximal mögliche Punktzahl im Test erreichen kann. 🙂

Lassen Sie uns also eine Variable max_score initialisieren. Und erfassen Sie die zurückgegebene Punktzahl der Funktion in der Variable final_score.

Anschließend fügen wir eine Assertion hinzu, die prüft, ob final_score kleiner oder gleich max_score ist.

def get_final_score(score,bonus):
    if bonus:
        score += 10
    return score

final_score = get_final_score(47,True)
max_score = 50

assert final_score <= max_score

Wir erhalten nun eine AssertionError-Ausnahme für den Funktionsaufruf get_final_score(47,True):

Traceback (most recent call last):
  File "main.py", line 17, in <module>
    assert final_score <= max_score
AssertionError

Fügen wir der assert-Anweisung nun einen beschreibenden F-String hinzu:

assert final_score <= max_score,f"Die Endpunktzahl sollte maximal {max_score} betragen; aktuelle Punktzahl: {final_score}"
Traceback (most recent call last):
  File "main.py", line 17, in <module>
    assert final_score <= max_score,f"Die Endpunktzahl sollte maximal {max_score} betragen; aktuelle Punktzahl: {final_score}"
AssertionError: Die Endpunktzahl sollte maximal 50 betragen; aktuelle Punktzahl: 57

Ändern der Funktion

Lassen Sie uns zur Definition der Funktion get_final_score zurückkehren und diese ändern, um das unerwartete Verhalten zu beheben:

  • Die Funktion get_final_score nimmt nun auch max_score als Parameter.
  • Wir prüfen, ob bonus wahr ist. Wenn ja, addieren wir 10 Punkte zur score-Variablen.
  • Dann prüfen wir, ob score größer als max_score ist. Wenn ja, geben wir max_score zurück.
  • Andernfalls geben wir die Punktzahl zurück.

Wir haben nun sichergestellt, dass die Endpunktzahl immer kleiner oder gleich max_score ist.

def get_final_score(score,bonus,max_score):
    if bonus:
        score += 10
    if score > max_score:
        return max_score
    return score

Schreiben Sie als schnelle Übung einige Assertions, um zu überprüfen, ob die Funktion jetzt wie erwartet funktioniert.

Ein Hinweis zur AssertionError-Ausnahme

Obwohl eine AssertionError-Ausnahme auftritt, wenn der Ausdruck als False ausgewertet wird, sollten wir daran denken, dass solche Fehler nicht als Ausnahmen zu behandeln sind. Das heißt, wir sollten so etwas nicht tun:

try:
    <doing this>
except AssertionError:
    <do this>

Im vorherigen Beispiel zu get_final_score haben wir die Assertion verwendet, um zu prüfen, ob final_score kleiner oder gleich max_score ist. Anschließend haben wir die Funktionsdefinition so modifiziert, dass keine Assertionsfehler auftreten.

Hierfür sind Assertions da. Sie sind Plausibilitätsprüfungen für Code und helfen beim Schreiben von sauberem Code. Die Ausnahmebehandlung hingegen dient dazu, unerwartete Fehler zur Laufzeit zu antizipieren und zu behandeln. Diese umfassen oft ungültige Eingabetypen und -werte.

Zusammenfassend lässt sich sagen, dass Sie die Python assert-Anweisung für effektives Debugging verwenden sollten und AssertionErrors nicht als Ausnahmen behandeln sollten.

Zusammenfassung

Dieses Tutorial hat Ihnen geholfen, die Anwendung der assert-Anweisung in Python zu verstehen. Hier eine Zusammenfassung der wichtigsten Punkte:

  • Python assert-Anweisungen (Assertions) haben die Form assert ausdruck. Diese überprüft, ob der Ausdruck True ist. Wenn dies nicht der Fall ist, wird eine AssertionError-Ausnahme ausgelöst.
  • Sie können die assert-Anweisung auch mit der Syntax assert ausdruck, meldung verwenden. Dadurch wird die Nachricht immer dann ausgegeben, wenn eine AssertionError-Ausnahme auftritt.
  • Sie sollten daran denken, keine Ausnahmebehandlung zu implementieren, um Assertionsfehler zu behandeln. Verwenden Sie Assertions stattdessen als nützliches Debugging-Tool für Plausibilitätsprüfungen Ihres Codes.

Als Entwickler helfen Ihnen Assertions beim Debuggen. Um sicherzustellen, dass alle einzelnen Komponenten (Module) des Projekts wie erwartet funktionieren, können Sie sich mit dem Schreiben von Unit-Tests in Python vertraut machen.

Als Nächstes können Sie sich diese Liste mit Python-Projekten für Anfänger ansehen, an denen Sie arbeiten können.