Frage zu try/except

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
maksimilian
User
Beiträge: 86
Registriert: Freitag 2. November 2018, 20:59

Hallo Ihr,

ich möchte in einem Python3-Skript erreichen, dass es bei einem fehlerhaften Datenbank-Connect nicht aussteigt. Mit folgendem Versuch scheitere ich:

Code: Alles auswählen

try:
    db=pymysql.connect(....)
except IOError:
   writelog(....)
cur=db.cursor()
Bei einem provozierten Fehler (ungültiger DB-Tabellenname) wird zwar except aufgerufen, das Skript aber nicht fortgesetzt. Wie muss ich vorgehen, um das zu verhindern ?

maksimilian
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@maksimilian: Wenn die Zuweisung an `db` nicht funktioniert, dann kannst Du natürlich in der letzten Zeile auf `db` zugreifen. ``try``/``except`` kennt auch einen ``else``-Zweig.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@maksimilian: im `except` einfach `writelog` aufzurufen löst ja Dein Problem nicht. Denn danach gibt es immer noch keine gültiges db-Objekt. Der Teil im `except`-Block muß das Programm wieder in einen Zustand bringen, mit dem es weiterarbeiten kann.

Was soll denn passieren, wenn es einen Connect-Fehler gibt? Was soll das Programm dann machen?
maksimilian
User
Beiträge: 86
Registriert: Freitag 2. November 2018, 20:59

Das Python-Skript wird in einem cron-Job aufgerufen und speichert Messdaten in einer Datenbank. Wenn die Verbindung zur DB nicht funktioniert, ist natürlich die Fortsetzung des Ablaufs nicht sinnvoll, Aufräumarbeiten und Dukumentieren des Fehlers sollen aber möglich sein.

Offensichtlich habe ich die Funktion von try/except noch nicht vollständig verstanden. Ich dachte, dass except Abbrüche durch Fehler verhindert. Die else Klausel wird nur bei fehlerfreiem Lauf durchlaufen.

maksimilian
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es verhindert diese Abbrüche ja auch. Nur kann es das doch nicht für das gesamte Programm magisch erledigen. Alle Funktionalität, die von der fehler-schmeißenden Code-Stelle betroffen ist, muss ebenfalls vor der Ausführung ausgenommen werden.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

maksimilian hat geschrieben: Mittwoch 5. Dezember 2018, 12:48 Offensichtlich habe ich die Funktion von try/except noch nicht vollständig verstanden. Ich dachte, dass except Abbrüche durch Fehler verhindert.
Mach dir einfach bewusst, dass man mit except einen Fehler behandelt, aber auch dass der Programmfluss nach der Behandlung weitergeht. Wenn du irgendwas loggen willst, dann ist das okay. Aber du solltest bei einem inkonsistenten Zustand (Verbindung wurde nicht erstellt und der Bezeichner db existiert nicht) möglichst aussteigen, da dann in der Regel keine sinnvolle Gegenmaßnahme möglich ist.

Man kann z.B. so etwas machen:

Code: Alles auswählen

def connect(uri):
    try:
        db = pymysql.connect(uri)
    except Exception as exc:
        writelog(exc)
        raise
    # Wird beim raise nicht erreicht
    return db
Ein raise ohne weitere Zusätze wirft den zuletzt abgefangenen Fehler erneut. Er loggt den Fehler also und zusätzlich kann darüber liegender Code eine eigene Fehlerbehandlung durchführen. Es wäre sinnvoll, z.B. beim Aufruf des Programms aus einer Shell eine Fehlermeldung via print() auszugeben. Dabei kann man durchaus den Fehlertext der Exception übernehmen, damit man kein allgemeines Blabla hat. Oder der Nutzer wird auf der Shell nach der korrekten URI gefragt. Je nachdem wie man das halt handhaben möchte. Aber man muss das eben ausprogrammieren.
Antworten