Probleme mit mySQL Verbindung

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,

    für die Auswertung von 5 Temperatursensoren habe ich ein kleines Script geschrieben.

    Das Script funktioniert bei 19 von 20 Durchläufen fehlerfrei.

    Das Script wird via Cronjob gestartet. Im Fehlerfall lasse ich mir den Fehler in eine Datei schreiben.

    Der Fehler lautet:

    Zwei weitere baugleiche Raspberrys laufen im gleichen Netz fehlerfrei.

    Das Script sieht wie folgt aus:

    Ein vielleicht wichtiger Hinweis noch: Das Script wird IMMER alle 15 Minuten ausgeführt. Wenn ein Fehler vorkommt, dann ist es immer bei 45 Minuten. Also z.B. 19:45, 22:45, 01:45

    An den Sensoren liegt es nicht, die Werte werden sauber in die CSV Datei geschrieben. In die Datenbank werden "nur" 3 der 5 Sensoren geschrieben.

    Mir gehen langsam die Ideen aus. Hat von euch jemand eine Idee?

    Danke & Grüße

    MSP

    Einmal editiert, zuletzt von hyle (21. August 2021 um 12:59) aus folgendem Grund: Zugangsdaten entfernt

  • Temporary failure in name resolution

    Das Problem ist imho die Namesauflösung, also DNS. Hast Du evtl. Pi-hole in Deinem Netzwerk laufen oder könntest Du sonst einen anderen DNS-Server verwenden?

    //Edit oder hat der Server vielleicht eine feste IP, die Du statt des Hostnamens verwenden kannst?

  • hyle Ich habe im Syslog gesehen das der Raspberry die Verbindung für paar Sekunden verliert und sich neu verbindet. Wenn das zusammen mit dem Scriptablauf passiert kommt es zum beschriebenen Fehler.

    Die Frage ist nur wieso er die Verbindung verliert. Die anderen zwei hängen am gleichen Switch und haben keine Probleme.

  • Die Frage ist nur wieso er die Verbindung verliert.

    Die Frage kann ich Dir leider nicht beantworten und wäre auch eher ein eigenständiges Thema im Bereich Netzwerk und Server. :conf: Mit Python scheint der hier auftretende Fehler nichts zu tun zu haben, sondern ist nur die Auswirkung darauf.

  • hyle ja richtig!

    Da die Abbrüche immer synchron mit dem Auslesen der Sensoren auftreten, gehe ich von einem Problem mit der Stromversorgung aus.

    Eventuell bricht die Spannung etwas ein während des Auslesens. Ich werde morgen testweise ein anderes Netzteil verwenden.

  • msp78: Anmerkungen zum Quelltext:

    `mysql` wird importiert, aber nirgends verwendet.

    Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

    Klassennamen werden per Konvention in PascalCase geschrieben, also in diesem Fall `Sensor`. So erkennt man Klassen und kann sie von anderen Datentypen unterscheiden, und man hat auch in der Regel immer einen generischen Namen für Exemplare, also hier beispielsweise ``sensor = Sensor(…)`` für ein konkretes `Sensor`-Objekt.

    Der Sensorname wird nirgends tatsächlich verwendet beziehungsweise ist in allen Fällen eine leere Zeichenkette die nichts am Ergebnis ändert an der Stelle wo sie verwendet wird. Das Attribut kann man also weg lassen.

    Die `print_temp()`-Methode hat einen falschen Namen, weil da überhaupt nichts ausgegeben wird. Da wird nur `read_temp()` aufgerufen und das Ergebnis in eine Zeichenkette umgewandelt. Dafür braucht man keine extra-Methode.

    Die Umwandlung/Formatierung in eine Zeichenkette würde man in neuem Code auch nicht mehr mit dem ``%``-Operator machen, sondern ein f-Zeichenkettenliteral verwenden.

    Jetzt bleibt als ”Klasse” eine Klasse mit einer `__init__()` und *einer* einzigen Methode übrig, die problemlos durch eine Funktion ersetzt werden kann.

    `temp` ist keine gute Abkürzung, weil das auch gerne als Abkürzung für `temporary` verwendet wird. Ich würde `temperature` einfach ausschreiben.

    Für das zusammensetzen von Pfadteilen verwendet man keine Zeichenkettenoperationen, dafür gibt es das `pathlib`-Modul. `Path`-Objekte haben dann auch gleich eine praktische Methode um den Text einer Datei als Zeichenkette einzulesen.

    Man sollte nur Ausnahmen behandeln die man auch erwartet und von denen man weiss, das man sie sinnvoll behandeln kann. Insbesondere wenn die Behandlung dann auch noch einfach komplett ignorieren ist. Was in dem ``try``-Block erwartbar ist, sind Fehler beim lesen der Datei, und dass der Text nach "t=" nicht in eine Gleitkommazahl umgewandelt werden kann. Und auch nur dass sollte man behandeln. Andere Ausnahmen, beispielsweise ein `NameError` weil man sich bei einem Namen vertippt hat, möchte man nicht einfach so ignorieren. Das macht die Fehlersuche zu einem Abenteuer das man sich ersparen kann.

    Fehlerwerte sind unschön, insbesondere wenn sie auch noch vom gleichen Datentyp sind wie normale Werte und im Grunde ein gültiger Wert sein können. Das bettelt gerade zu danach Folgefehler zu erzeugen wenn irgendwo dann doch mal mit diesem Wert weitergearbeitet werden sollte, ohne ihn vorher heraus zu filtern oder anderweitig gesondert zu behandeln.

    Bei Gleitkommazahlen könnte man noch NaN als Fehlerwert verwenden, weil das nicht unüblich ist nicht vorhandene Werte mit diesem Wert zu kodieren. Ganz allgemein ist `None` in Python der Wert, der für „keinen Wert“ steht. Beides kann man nicht einfach aus versehen als Temperaturwert verrechnen ohne das es auffällt.

    Man nummeriert keine Namen durch. Da will man entweder bessere Einzelnamen verwenden, oder gar keine einzelnen Namen, sondern eine Datenstruktur. Oft eine Liste. So auch in diesem Fall.

    Die Temperaturwerte werden zu früh in Zeichenketten umgewandelt. In die Datenbank will man Zahlen speichern, keine Zeichenketten. Das MySQL-Connector das so erlaubt ist ein Implementierungsdetail, da würde man eigentlich eine Ausnahme erwarten. Und ausserdem hängt der Dezimaltrenner hier von den Datenbankeinstellungen ab. Wenn man Gleitkommazahlen übergibt, ist es egal ob die Datenbank auf "." oder "," für die Darstellung von Gleitkommazahlen/DECIMAL & Co eingestellt ist. Und `None` wird auf NULL abgebildet, was bei `read_temp()` für `None` als Fehlerwert sprechen würde, denn das ist ja in SQL-Datenbanken genau der Wert für „kein Wert“.

    Es wird 5-mal `strftime()` aufgerufen, wobei jedes mal der Zeitpunkt neu bestimmt wird obwohl sich das eigentlich alles auf *einen* Zeitpunkt beziehen soll. Das ist ein Fehler, weil es so vorkommen kann, dass die Werte nicht zusammenpassen, und man am Ende Zeitpunkte speichert, die bis zu einem Tag vom tatsächlichen Zeitpunkt abweichen.

    Eigentlich wäre es besser UTC statt lokale Zeit aufzuzeichnen, dann bekommt man keine Probleme mit der Umstellung zwischen Sommer- und Winterzeit, wo es dann entweder eine Lücke gibt, oder sich eine Stunde wiederholen kann.

    Der Zeitpunkt ist *ein* Wert, den sollte man nicht künstlich aufteilen. Insbesondere in der Datenbank nicht, denn SQL-Datenbanken haben dafür mit TIMESTAMP extra einen Datentyp für. Und auch hier sollte man genau wie bei den Zahlen keine Zeichenketten übergeben, sondern die entsprechenden Objekte.

    Der Datenbankentwurf ist kaputt. Weder sollten Tabellennamen noch Spaltennamen irgendwelche Nummern enthalten. Du steckst da Daten die eigentlich in die Tabelle(n) gehören, in die Metadaten. Man würde hier eine Tabelle für Temperaturwerte verwenden in der Raum- und Sensor-ID in Spalten gespeichert werden.

    Ungetestet:

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!