Programm stürzt ab, wenn SQL Verbindung nicht funktioniert

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
kanuddel
User
Beiträge: 6
Registriert: Montag 31. August 2020, 22:57

Hallo,

ich bin noch recht neu im Thema und bin mir daher nicht sicher, ob ich es richtig erkannt habe, wann der Fehler passiert.

Grundsätzlich habe ich ein Programm geschrieben dass Werte in eine SQL Datenbank schreibt. Das funktioniert auch soweit. Nur manchmal stürzt es ab, wenn versucht wird, die Verbindung zum SQL Server aufzubauen. Ob da nun der Raspi, auf dem das Programm läuft, offline ist, oder ob die Datenbank in dem Moment offline ist, weiß ich nicht.

Das Programm wirft dann einen Fehler und beendet sich. Ich hätte natürlich gerne, dass sich das Programm deswegen nciht beendet, sondern eben lieber 1x nichts einträgt und dann dafür weiterläuft und beim nächsten durchlauf der Funktion wieder versuht etwas einzutragen (irgendwann ist der Raspi oder die DB wieder online)

Hier die Fehlermeldung die mir Python wirft:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/network.py", line 485, in open_connection
    socket.SOL_TCP)
  File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -3] Temporary failure in name resolution

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/Desktop/python/temperaturen2.py", line 81, in <module>
    con = mysql.connector.connect(**DATABASE_CONFIG) #datenbank verbindung
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/__init__.py", line 179, in connect
    return MySQLConnection(*args, **kwargs)
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/connection.py", line 95, in __init__
    self.connect(**kwargs)
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/abstracts.py", line 716, in connect
    self._open_connection()
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/connection.py", line 206, in _open_connection
    self._socket.open_connection()
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/network.py", line 501, in open_connection
    errno=2003, values=(self.get_address(), _strioerror(err)))
mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'xxxmeinsqlserverxxx' (-3 Temporary failure in name resolution)
Mein Code schaut so aus:

Code: Alles auswählen

con = mysql.connector.connect(**DATABASE_CONFIG) #datenbank verbindung
try:
    cursor = con.cursor()
    query = ...
    values = ...
    cursor.execute(query, values)
    con.commit()
except mysql.connector.Error as error:
    print("Oh no, something went wrong.\nIt was: {error}")
    print("I don't know what to do, so I raise the exception!")
    cursor.close()
    raise
Nun wär die Frage, wie ich den Code umändern müsste, damit er die Ausführung nicht stoppt, sondern weitermacht.

Ich bedanke mich für eure Hilfe!

Viele Grüße,
kanuddel
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Du musst den Fehler da fangen, wo er auftritt.

In dem Traceback, den du gepostet hast, siehst du ja welcher Fehler an welcher Stelle in deinem Code auftritt. Das ist aber die einzige Zeile, die du nicht "absicherst".
Du versuchst in except-Block den Cursor zu schließen. Was denkst du, was passiert, wenn er noch gar nicht geöffnet wurde?

Das "raise" im except-Block wird dazu führen, dass der Fehler so oder so nach oben weitergereicht wird. Wird er dort nicht entsprechend abgefangen, wird das Programm dann abbrechen.

Das Tutorial hat ein gutes Kapitel über Exceptions und wie man damit umgeht.
kanuddel
User
Beiträge: 6
Registriert: Montag 31. August 2020, 22:57

Also so ganz hab ich das noch nicht verstanden.


Ich hätte das jetzt so umgesetzt:

Code: Alles auswählen

except socket.gaierror as error:
	print("Oh no, something went wrong.\nIt was: {error}")
	raise
ode rmüsste ich das cursor.close aus der anderen exception rausnehmen? Oder bin ich total auf dem Holzweg?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du verbindest dich *ausserhalb* deines try except. Wie soll das denn dann abgefangen werden?
kanuddel
User
Beiträge: 6
Registriert: Montag 31. August 2020, 22:57

Nachdem die Verbindung nun innerhalb des Try except ist, stürzt es kaum noch ab.
Gerade war es wieder mal soweit und gab mir folgenden Fehler:

Code: Alles auswählen

Oh no, something went wrong.
It was: {error}
I don't know what to do, so I raise the exception!
Traceback (most recent call last):
  File "/home/pi/Desktop/python/temperaturen2.py", line 82, in <module>
    con = mysql.connector.connect(**DATABASE_CONFIG) #datenbank verbindung
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/__init__.py", line 179, in connect
    return MySQLConnection(*args, **kwargs)
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/connection.py", line 95, in __init__
    self.connect(**kwargs)
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/abstracts.py", line 716, in connect
    self._open_connection()
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/connection.py", line 210, in _open_connection
    self._ssl)
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/connection.py", line 144, in _do_auth
    self._auth_switch_request(username, password)
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/connection.py", line 157, in _auth_switch_request
    packet = self._socket.recv()
  File "/home/pi/.local/lib/python3.7/site-packages/mysql/connector/network.py", line 243, in recv_plain
    raise errors.InterfaceError(errno=2013)
mysql.connector.errors.InterfaceError: 2013: Lost connection to MySQL server during query
Wie müsste ich dann das abfangen? Kann ich nicht irgendie "alles" abfangen, sodass das Programm dann zumindest weiterläuft, auch wenn dann eben nichts eingetragen wird?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst das abfangen, indem du auch diese Ausnahme der Liste der bekannten (und zu ignorierenden) Ausnahmen hinzufügst.

Es gibt einen Weg, alles abzufangen. Inklusive all der Programmierfehler, die du machst, und auf die du dann niemals kommst. Darum macht man das nicht.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: in diesem Fall kann man das machen, wenn man im except-Block den Traceback ausgibt.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Wenn ich das richtige Modul erwischt habe (ich bin bei mariaDB/mySQL nicht im Thema), dann müsste das hier das Modul sein, dass die Exceptions beinhaltet. Die scheinen alle von mysql.connector.errors.error abgeleitet zu sein. Vielleicht wäre es sinnvoll, nur diese Exceptions zu fangen - für den Fall dass noch etwas auftreten kann, was man nicht auf dem Schirm hat und das man nicht durch eine neue Verbindung zu Datenbank 'reparieren' kann. Und das Auftreten sollte gelogt werden.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sirius3 hat geschrieben: Mittwoch 25. November 2020, 07:37 @__deets__: in diesem Fall kann man das machen, wenn man im except-Block den Traceback ausgibt.
Kann man ja immer. Warum also sollte man das hier machen, aber generell nicht?
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Schwierigkeit wenn man alle Fehler abfängt ist ja, dass man bei unbekannten Fehlern nicht weiß, wie man sinnvoll weiterarbeiten soll. Hier geht es nur darum, dass bei irgendeinem Fehler das Programm mit der nächsten Messung weiter machen soll.
Antworten