Also ich hatte es jetzt immer so gemacht, dass bei except der requests.StatusCode ausgegeben wird und wie erwartet waren bzw. sind es Netzwerkprobleme.
Einmal war es Fehlercode 502, einmal jetzt Fehlercode 500
Wie komme ich aber zurück in die (Endlos-)Schleife? Trotz continue bleibt das Skript stehen... ?!
Skript bricht immer nach etwa 4 Stunden ab?!
Wie sieht denn Dein Skript jetzt aus? `continue` ist nicht dazu da, nach einem Fehler magisch fortzusetzen. Das ist dazu da, bei Schleifen wieder an den Anfang zu springen, was man eigentlich im Normalfall nicht machen sollte.
- __blackjack__
- User
- Beiträge: 14020
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Chrissili: Die HTTP-Fehler 502 und 500 sind keine Netzwerkprobleme, jedenfalls nicht direkt. Wie willst Du denn darauf reagieren? Warum gibt es diese Fehler und wie kannst Du da sinnvoll weiter machen? Und von wo kommen die Fehler, von der externen URL oder da wo Du die Temperaturen abfragst?
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Also die Fehler kommen denke ich wenn https://Server.growatt.com nicht erreichbar ist oder meine Homematic Station unter http://192.168.178.22:8181
Am liebsten wäre es mir, wenn das Skript dann "einfach" 5 oder 10 Minuten wartet und dann es erneut versucht oder von vorne startet.
Am liebsten wäre es mir, wenn das Skript dann "einfach" 5 oder 10 Minuten wartet und dann es erneut versucht oder von vorne startet.
- __blackjack__
- User
- Beiträge: 14020
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Chrissili: Da denkst Du falsch. Wenn ein HTTP-Server mit einem HTTP-Fehlercode *antwortet*, war er ja offensichtlich erreichbar, sonst hätte er schlecht antworten können.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Wobei die Unterscheidung ja ein bisschen egal ist. Relevant ist: das Skript muss in dem Moment eben robust damit umgehen. Fehler abfangen, warten, neu probieren ist ja alles kein Hexenwerk. Wie wurde ja sogar schon gezeigt, und ganz allgemein sind Fehlerbehandlung und "Dinge wiederholt tun" ja Teil des Grundlagentutorials.
Wo kann ich denn das Grundlagentutorial dann dazu nochmal studieren? Mit dem Continue bin ich ja dann immer nur ins "finally: " reingerutscht und hab es leider nicht nach einer gewissen Wartezeit zurück in die "while True: " schleife geschafft...
https://docs.python.org/3/tutorial/intr ... rogramming und folgende. Ein Verstaendnis fuer die grundlegenden Kontrollstrukuren ist unabdingbar.
Hallo,
Schleifen, 'if'-Abfragen sind Teile der Kontrollstruktur. Der Name sagt schon, dass es dabei geht die Kontrolle über den Programmablauf zu haben. Was mache ich, wenn dies und jenes passiert und zwischen drin noch ein Fehler auftritt.(?) Genau dort beginnt auch das verlinkte Tutorial.
Grüße
Dennis
Schleifen, 'if'-Abfragen sind Teile der Kontrollstruktur. Der Name sagt schon, dass es dabei geht die Kontrolle über den Programmablauf zu haben. Was mache ich, wenn dies und jenes passiert und zwischen drin noch ein Fehler auftritt.(?) Genau dort beginnt auch das verlinkte Tutorial.
Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Sorry ich habe mittlerweile sicher viel zu Grundlagen gelesen und verstehe auch wie man bei diesen mathematischen Modulo-Divisions-Beispielen break oder continue verwendet aber es funktioniert in meinem http Fall irgendwie nicht.
Aktuell hab ich das entscheidende in meinem Skript grob so:
Ich bekomme sowohl manchmal Fehlermeldung 1 als auch Fehlermeldung 2, aber danach ist irgendwie Schluss und das Skript läuft nicht weiter?! Warum?! Ich dachte mit continue soll er weiterlaufen?
Aktuell hab ich das entscheidende in meinem Skript grob so:
Code: Alles auswählen
While True:
if requests.status_code == 200:
try:
*hauptprogramm*
except:
print Fehlermeldung1
continue
else:
print Fehlermeldung2
continue
Ich bekomme sowohl manchmal Fehlermeldung 1 als auch Fehlermeldung 2, aber danach ist irgendwie Schluss und das Skript läuft nicht weiter?! Warum?! Ich dachte mit continue soll er weiterlaufen?
Also das entscheidende Grobe funktioniert hier. Dann kann es nur noch an den ebenso entscheidenden Details liegen...
Wird den zwischen
und
oder vor den der Statuscode irgendwie wieder aktualisiert und auf einen neuen Stand gebracht?
Wird den zwischen
Code: Alles auswählen
While True:
Code: Alles auswählen
if requests.status_code == 200:
Code: Alles auswählen
continue
_______________________________________________________________________________
https://www.python-kurs.eu/index.php
https://learnxinyminutes.com/docs/python/ https://learnxinyminutes.com/docs/de-de/python-de/
https://quickref.me/python https://docs.python-guide.org/
- __blackjack__
- User
- Beiträge: 14020
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Chrissili: Dieser Pseudocode nützt nicht viel, weil das ja nicht der Code ist, der bei Dir läuft. ``while`` schreibt man klein. Das `requests`-Modul hat kein `status_code`-Attribut. Es gibt auch noch andere Codes als genau 200 die für OK stehen. Du hast im Original mehrere HTTP-Anfragen, das heisst, das kann gar nicht so strukturiert sein, dass an einer Stelle ”der” Status abgefragt wird, denn bevor man das machen kann, muss man ja die Anfragen machen, und *jede* davon kann fehlschlagen. Man verwendet keine ”nackten” ``except:`` ohne konkrete Ausnahme(n). Das macht die Fehlersuche schwer bis unmöglich. Da kommen nur die Ausnahmen rein, die man erwartet und die man deshalb sinnvoll so behandeln kann. Und beide ``continue``-Anweisungen in dem Pseudocode haben keinen Effekt, weil auch ohne die Anweisung nichts anderes passiert als der nächste Schleifendurchlauf.
Ist denn auch tatsächlich sinnvoll einfach so mit dem nächsten Schleifendurchlauf weiter zu machen und die alten Werte auf dem LCD-Display stehen zu lassen? Auch wenn da ein Zeitstempel bei dem einen Informationssatz steht — wenn der älter ist, als zu erwarten wäre, weiss der Betrachter nicht ob der alte Wert vom Webdienst kam, oder der alte Wert dort steht, weil kein neuerer abgerufen werden konnte. Bei der Temperatur würde der Betrachter des Displays gar nicht mitbekommen wenn der Wert veraltet ist, weil die Abfrage nicht geklappt hat.
Es macht Sinn bei Diensten bei unerwarteten Ausnahmen, die vom Programm behandelt werden in dem sie ignoriert werden, möglichst viel zu protokollieren. Also mindestens mit dem `logging`-Modul aus der Standardbibliothek die Ausnahme samt Traceback. Ich mag das externe `loguru`, weil das noch ein paar Informationen zu lokalen Variablen mit in den Traceback packt, die bei der Fehler-/Ursachensuche hilfreich sein können.
Ist denn auch tatsächlich sinnvoll einfach so mit dem nächsten Schleifendurchlauf weiter zu machen und die alten Werte auf dem LCD-Display stehen zu lassen? Auch wenn da ein Zeitstempel bei dem einen Informationssatz steht — wenn der älter ist, als zu erwarten wäre, weiss der Betrachter nicht ob der alte Wert vom Webdienst kam, oder der alte Wert dort steht, weil kein neuerer abgerufen werden konnte. Bei der Temperatur würde der Betrachter des Displays gar nicht mitbekommen wenn der Wert veraltet ist, weil die Abfrage nicht geklappt hat.
Es macht Sinn bei Diensten bei unerwarteten Ausnahmen, die vom Programm behandelt werden in dem sie ignoriert werden, möglichst viel zu protokollieren. Also mindestens mit dem `logging`-Modul aus der Standardbibliothek die Ausnahme samt Traceback. Ich mag das externe `loguru`, weil das noch ein paar Informationen zu lokalen Variablen mit in den Traceback packt, die bei der Fehler-/Ursachensuche hilfreich sein können.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Hallo ihr Lieben, also darf ich euch nochmal mein aktuelles Skript posten?
Hoffe das bringt etwas Klarheit:
Hoffe das bringt etwas Klarheit:
Code: Alles auswählen
import requests
from rpi_lcd import LCD
from time import sleep
session = requests.Session()
try:
response = session.post("https://server.growatt.com/login", data={
"account": "abc",
"password": "abc",
"validateCode": "",
"isReadPact": "0",
})
lcd = LCD()
except:
print("LCD initial fehler")
while True:
sleep(1)
if response.status_code == 200:
try:
response = session.post("https://server.growatt.com/panel/getDevicesByPlantList", data={"currPage": "1","plantId": "abc"})
g = response.json()
response = session.post("https://server.growatt.com/panel/storage/getStorageStatusData", data={"typ": "STORAGE", "plantId": "abc", "storageSn": "abc"})
l = response.json()
response = session.post("https://server.growatt.com/panel/storage/getStorageTotalData", data={"typ": "STORAGE","plantId": "abc", "storageSn": "abc"})
m = response.json()
lcd.text(g.get('obj').get('datas')[0].get('lastUpdateTime'), 1)
lcd.text("PV " + l.get('obj').get('ppv1') + "W | Netz " + l.get('obj').get('gridPower') + "W", 2)
lcd.text("Bat " + l.get('obj').get('batPower') + "W | VB " + l.get('obj').get('loadPower') + "W", 3)
lcd.text("Bat " + l.get('obj').get('capacity') + "% | Tag " + m.get('obj').get('epvToday') + "kWh", 4)
sleep(4)
except:
lcd.text("Fehler Except innen", 1)
lcd.text(g.get('obj').get('datas')[0].get('lastUpdateTime'), 2)
lcd.text("Response Status " + str(response.status_code), 3)
continue
else:
lcd.text("Fehler Else", 1)
lcd.text(g.get('obj').get('datas')[0].get('lastUpdateTime'), 2)
lcd.text("Response Status " + str(response.status_code), 3)
continue
Zuletzt geändert von grubenfox am Donnerstag 30. März 2023, 11:56, insgesamt 1-mal geändert.
_______________________________________________________________________________
https://www.python-kurs.eu/index.php
https://learnxinyminutes.com/docs/python/ https://learnxinyminutes.com/docs/de-de/python-de/
https://quickref.me/python https://docs.python-guide.org/
Warum logst du dich nur einmal ein? Weisst du, wie lange der login Gueltigkeit hat? Vielleicht 4h? Und wenn der Login *nicht* funktioniert (warum auch immer, kann ja auch temporaer sein), wieso laeuft dein Programm dann weiter? Und was hat das LCD damit zu tun, dass da ein Fehler aufgetreten ist?
Was meinst du in welcher Zeile?grubenfox hat geschrieben: Donnerstag 30. März 2023, 11:45 viewtopic.php?p=418698#p418698
P.S. ... und in welcher Zeile?
Das weiß ich leider nicht wie lange da die Gültigkeit ist.__deets__ hat geschrieben: Donnerstag 30. März 2023, 11:54 Warum logst du dich nur einmal ein? Weisst du, wie lange der login Gueltigkeit hat? Vielleicht 4h? Und wenn der Login *nicht* funktioniert (warum auch immer, kann ja auch temporaer sein), wieso laeuft dein Programm dann weiter? Und was hat das LCD damit zu tun, dass da ein Fehler aufgetreten ist?
LCD hat damit natürlich nix zu tun...sorry für die unpräzise Formulierung
- __blackjack__
- User
- Beiträge: 14020
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Chrissili: Du versuchst da viel zu viel auf einmal zu machen und alles wird munter vermischt und es wird Quelltext wiederholt. Das Hauptprogramm gehört in eine Funktion. Die Hauptschleife könnte man auch in eine eigene Funktion auslagern, siehe den Quelltext von Sirius3. Und ich hatte ja schon geschrieben, dass das alles in einer Funktion auch immer noch zu viel sein könnte. Und selbst innerhalb nur einer Funktion die alles von der Hauptschleife abdeckt, sollte man sauber zwischen dem Abfragen/Ermitteln der Information und der Anzeige der Informationen trennen.
Nackte ``except:`` ohne eine konkrete Ausnahme sind nicht sinnvoll. Das Einzige was dort wirklich Sinn macht, ist das möglichst detaillierte protokollieren der Ausnahme. Sonst ist die Fehlersuche nahezu unmöglich.
Die erste Fehlerbehandlung behauptet das das LCD nicht initialisiert werden konnte, auch wenn das Problem beim Netztwerk/der Anmeldung beim Server gelegen hat. Und dann läuft der Code einfach weiter und versucht dann von dem Server an dem die Anmeldung nicht durchgeführt wurde, Informationen abzufragen und/oder auf dem LCD das nicht initialisiert werden konnte, Informationen darzustellen. Um dann dort wieder in Fehler zu laufen, die unter Umständen dann wieder in einem ``except`` landen, wo dann auch wieder eine vorhersehbare Ausnahme ausgelöst wird, denn `g` (über schlechte Namen hatten wir auch schon mal gesprochen!) wird sicher nicht die Daten enthalten die da erwartet werden, wenn man am Server gar nicht angemeldet ist.
Die erste Fehlerbehandlung würde man einfach weg lassen, denn wenn man sich nicht anmelden konnte oder das Display nicht geht, dann braucht das Programm nicht weiterlaufen, und man hätte auch sicher gerne bessere Information um dem Fehler auf die Spur zu kommen.
``response.status_code`` bezieht sich beim ersten Durchlauf auf die Anmeldung am Server und bei den weiteren Durchläufen — kann man das gar nicht sicher sagen auf welches der drei `Response`-Objekte sich das beziehen mag, denn jeder davon könnte ja auch fehlschlagen. Man muss da schon *jede* Abfrage berücksichtigen. Und wenn man beispielsweise `Response.raise_for_status()` benutzt, muss man in dem entsprechenden ``except (…, …) as error:`` auch damit rechnen das es auch jede Anfrage innerhalb des ``try`` gewesen sein könnte, und nicht einfach Namen verwenden die entweder deshalb noch gar nicht existieren, oder einen veralteten Wert vom vorherigen Schleifendurchlauf besitzen.
Die beiden ``continue``-Anweisungen haben an der Stelle wie vermutet keinen Effekt, weil sie den Programmablauf nicht beeinflussen. Da passiert mit und ohne diese Anweisungen genau das gleiche. Ich würde von ``continue`` sowieso die Finger lassen, weil das unnötig undurchsichtig ist. Es gibt zu ``try``/``except`` auch ein ``else`` falls man das tatsächlich brauchen sollte. Wie gesagt, hier einfach überflüssig (bis jetzt).
Nackte ``except:`` ohne eine konkrete Ausnahme sind nicht sinnvoll. Das Einzige was dort wirklich Sinn macht, ist das möglichst detaillierte protokollieren der Ausnahme. Sonst ist die Fehlersuche nahezu unmöglich.
Die erste Fehlerbehandlung behauptet das das LCD nicht initialisiert werden konnte, auch wenn das Problem beim Netztwerk/der Anmeldung beim Server gelegen hat. Und dann läuft der Code einfach weiter und versucht dann von dem Server an dem die Anmeldung nicht durchgeführt wurde, Informationen abzufragen und/oder auf dem LCD das nicht initialisiert werden konnte, Informationen darzustellen. Um dann dort wieder in Fehler zu laufen, die unter Umständen dann wieder in einem ``except`` landen, wo dann auch wieder eine vorhersehbare Ausnahme ausgelöst wird, denn `g` (über schlechte Namen hatten wir auch schon mal gesprochen!) wird sicher nicht die Daten enthalten die da erwartet werden, wenn man am Server gar nicht angemeldet ist.
Die erste Fehlerbehandlung würde man einfach weg lassen, denn wenn man sich nicht anmelden konnte oder das Display nicht geht, dann braucht das Programm nicht weiterlaufen, und man hätte auch sicher gerne bessere Information um dem Fehler auf die Spur zu kommen.
``response.status_code`` bezieht sich beim ersten Durchlauf auf die Anmeldung am Server und bei den weiteren Durchläufen — kann man das gar nicht sicher sagen auf welches der drei `Response`-Objekte sich das beziehen mag, denn jeder davon könnte ja auch fehlschlagen. Man muss da schon *jede* Abfrage berücksichtigen. Und wenn man beispielsweise `Response.raise_for_status()` benutzt, muss man in dem entsprechenden ``except (…, …) as error:`` auch damit rechnen das es auch jede Anfrage innerhalb des ``try`` gewesen sein könnte, und nicht einfach Namen verwenden die entweder deshalb noch gar nicht existieren, oder einen veralteten Wert vom vorherigen Schleifendurchlauf besitzen.
Die beiden ``continue``-Anweisungen haben an der Stelle wie vermutet keinen Effekt, weil sie den Programmablauf nicht beeinflussen. Da passiert mit und ohne diese Anweisungen genau das gleiche. Ich würde von ``continue`` sowieso die Finger lassen, weil das unnötig undurchsichtig ist. Es gibt zu ``try``/``except`` auch ein ``else`` falls man das tatsächlich brauchen sollte. Wie gesagt, hier einfach überflüssig (bis jetzt).
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.