neustart/reboot über eine Exception

  • Hallo Experten, folgende Frage:
    Habe mit einem Raspberry P 3, PIR Sensor und NoIR PiCamera eine Hausüberwachungsanlage gebaut die

    gut funktioniert. Das Script: "https://gist.github.com/luemar/17d7659c26a0beac9fb4f4259aadefd3.js


    Im Langzeitbetrieb über Stunden, Tage und mehr treten gelegentlich Fehler auf (beobachtet bei

    der email und camera Funktion), die dann das Script beenden, nicht im Sinne des Erfinders.


    Nun die Frage, um eine uneingeschränkte Funktion zu garantieren, wie könnte ich, indem ich das ganze Script mit try und except absichere

    um jeden Fehler abzufangen, die Exception veranlassen, das Script neu zu starten oder allenfalls den RPI zu rebooten wobei das Script dann

    mittels Eintrag in /etc/rc.localneu gestartet würde,


    Geht das überhaupt ? Luemar.

  • Nun die Frage, um eine uneingeschränkte Funktion zu garantieren, wie könnte ich, indem ich das ganze Script mit try und except absichere

    um jeden Fehler abzufangen

    Jeden Fehler fängt man nicht ab (etwa mit einem except Exception:). Wenn du Fehler erwartest, fange diese gezielt ab und lasse das Script somit weiterlaufen. Neu starten kannst du das Script im Falle eines Absturzes meines Wissens nach am leichtesten mit einer Systemd Service Unit.

    Wir können allerdings nicht hellsehen und werden nicht anfangen, Exceptions zu raten ;)

    Die Verlinkung deines Gists ist gnadenlos fehlgeschlagen.

  • 2. Wo kann ich über die Systemd Service Unit nachlesen ? Kenne mich nicht aus

    Das ist in 10 Zeilen nicht erklärt.


    Auch nicht in 100m oder 1000.

    Ohne systemd funktioniert das Pi-Linux nicht.


    Eine Möglichkeit wäre hier ( https://wiki.ubuntuusers.de/systemd/ ) anzufangen und die Links durchzuackern.


    Ohne Internet stellr < man systemd > und dessen SEE ALSO jede Menge Infos z.V.



    Servus !

  • wobei das Script dann

    mittels Eintrag in /etc/rc.localneu gestartet würde,


    Geht das überhaupt ?

    Gehen tut das, aber es ist die schlechteste Lösung. Starte das Script über eine systemd-service-unit und überlasse systemd die Überwachung. Mit richtiger Einstellung startet systemd den Service automatisch neu, sobald er gestorben ist. Den Rechner zu rebooten ist dafür nicht notwendig. Am Script musst du auch nix ändern, nur die kleine Unit mit etwa 10 Zeilen schreiben.

    Eine komplette Lösung findest du in diesem Thread

    https://debianforum.de/forum/viewtopic.php?f=34&t=168838


    Achte dabei auf scientifics Beiträge, der ist Fachmann für systemd und man kann sich drauf verlassen, dass das korrekt ist.

  • 1.Aber wenn die Exception auftritt läuft das Script ja nicht weiter sondern wird

    mit sys.exit() beendet. Müsste ich dann besser pass eingeben ?

    Oh, da besteht Nachholbedarf. Vielleicht fängst du hier an, um das Konzept zu verstehen: https://docs.python.org/3/tutorial/errors.html

  • Hallo Experten,

    1. das heisst, dass ich alle 3 der mittel der Module picamera, smtplib und pushbulletin

    definierten Funktionen separat mittels try/except abzusichern muss nachdem im Langzeittest

    in allen 3 Fehler mit konsekutiven Abstürzen aufgetreten sind.

    Ist das richtig ?


    2. Wie kann aus einem Python Script eine Anweisung an systemd gegeben werden, das Script neu zu starten ?


    Bind dabei systemd zu "verdauen", ist aber ein grosser Brocken für einen Hobbyisten.

  • 2. Wie kann aus einem Python Script eine Anweisung an systemd gegeben werden, das Script neu zu starten ?

    Warum willst du das tun? Nochmal: du fängst einfach gezielt die Exceptions ab, die nach deinen Beobachtungen auftreten könnten. Bist du daran schuld, solltest du sie natürlich fixen ;)

    nachdem im Langzeittest in allen 3 Fehler mit konsekutiven Abstürzen aufgetreten sind.

    (darauf bezogen, ich kann ja nicht hellsehen)


    Dann stürzt dein Skript auch nicht mal eben ab, sofern gut programmiert. Und wenn doch, Systemd kann es ja auch ohne externe Anweisung wieder starten.

  • ...beginne es langsam zu begreifen und bin ziemlich sicher, dass kein Programmierfehler vorliegt

    (nehme den Mund jetzt mal etwas voll):


    Wenn ich also die tracebacks in den Funktionen meines Scripts mit den richtigen

    (built-in) Exceptions abfange geht das Script weiter bzw. der Code unter try: wird erneut

    ausgeführt. Richtig ?


    D.h für mich, wenn der Fehler weiter besteht gibt das eine Schlaufe zwischen try: und except:

    bis der Fehler nicht mehr vorkommt.


    In der Langzeit Testphase sind verschiedene, unterschiedliche tracebacks aufgetreten und ich weiss

    nicht, wie ich alle möglichen Fehlerkategorien bzw. exception Typen prospektiv erfassen kann.

  • D.h für mich, wenn der Fehler weiter besteht gibt das eine Schlaufe zwischen try: und except:

    bis der Fehler nicht mehr vorkommt.

    Beispiel: du versuchst ne Datei zu öffnen um etwas auszulesen. diese wird von einem anderen Programm erstellt und nach einer Zeit wieder gelöscht. Es kann also vorkommen, dass diese Datei beim öffnen nicht da ist. du kannst also versuchen das generell so zu machen. Egal welcher Fehler auftritt, ignorier es und mach weiter


    Code
    1. while True:
    2. try:
    3. with open("bla.txt","r") as f:
    4. f.readlines()
    5. except:
    6. pass

    Das funktioniert tadellos, drückt dir aber auch Fehler weg die du eventuell sehen willst. Eigentlich willst du ja bloss, den "Datei-nicht-da-Fehler" abfangen

    Code
    1. while True:
    2. try:
    3. with open("bla.txt","r") as f:
    4. f.readlines()
    5. except FileNotFoundError:
    6. pass


    aber ja, solange rattert er zwischen den try und except hin und her.

    Der Unterschied zwischen Genie und Wahnsinn definiert sich im Erfolg.

  • (built-in) Exceptions

    Wieso nur Built-In? Du kannst auch Exceptions, die in 3rd-party-packages definiert sind, abfangen :conf:

    geht das Script weiter

    Ja.

    bzw. der Code unter try: wird erneut ausgeführt.

    Nein.

    D.h für mich, wenn der Fehler weiter besteht gibt das eine Schlaufe zwischen try: und except:

    bis der Fehler nicht mehr vorkommt.

    Nein. Nur wenn du das explizit so programmierst, etwa mit einer Schleife.

    In der Langzeit Testphase sind verschiedene, unterschiedliche tracebacks aufgetreten und ich weiss

    nicht, wie ich alle möglichen Fehlerkategorien bzw. exception Typen prospektiv erfassen kann.

    Die genauen Exceptions musst du dir schon merken. Dann lasse dein Skript eben weiterhin ohne die neue Fehlerbehandlung laufen und notiere dir jedes mal, wenn eine Exception auftritt deren Namen. Dann kannst du starten, geziehlt abzufangen.


    Vorher noch im Internet danach suchen, eventuell ist es ja doch Fehlbedienung durch dich :fies:

    Denn normalerweise fängt ein Programmnicht an, mit Exceptions um sich zu werfen, auch nicht, wenn es lange läuft. Das ist fast immer ein Fehler des Programmierers.

  • Das passiert wenn man ohne richtigen Editor tippt. Ich bin so gewohnt, dass das automatisch passiert. Trotzdem rattert er zwischen den Try und Except hin und her (bzw immer wieder drüber), offensichtliche Tipfehler mal abgesehen.

    Der Unterschied zwischen Genie und Wahnsinn definiert sich im Erfolg.

  • 2. Wie kann aus einem Python Script eine Anweisung an systemd gegeben werden, das Script neu zu starten ?

    Das steht in dem genannten Thread beschrieben. Eigentlich ist es nur notwendig, das Programm (quasi als Daemon) via Systemd zu starten. Systemd überwacht den Prozess, wenn er stirbt, wird er automatisch neu gestartet. Also, wie gesagt, systemd kannn sowas schon von Hause aus. Siehe "restart=on-failure" in 'man systemd.service" , um einen gestorbenen Prozess automatisch neu zu starten. Oder alternativ, siehe "OnFailure=" in 'man systemd.unit'. Wie eine passende Service-Unit aussieht, steht im genannten Thread beschrieben.


    Und meine Meinung.... wenn Du so ein 24/7-System betreust und bestimmte Dienste einrichtest, dann gehören Kenntnisse zu systemd zu den zwingend notwendigen Kenntnissen... alles andere ist Autofahren mit rundrum vereisten Scheiben... und ankommen ist dabei Glücksache. Du sollte also schon wissen, wie man ein Programm als Dienst einrichtet und in der Folge die Überwachung von Systemd nutzen kann.

  • ...vielen Dank für die Hinweise/Support, muss mir aber nun Klarheit verschaffen:


    1. Programmierung: Bin zwar nur etwas fortgeschrittener Anfänger und halte mich für ziemlich selbstkritisch.

    Aber die selbe Funktion, - Link im obersten Thread - die immer wieder tracebacks mit Programmende verursacht

    funktioniert in einem anderen, einfacheren Script, welches unter /etc/crontab jeden Tag ein Bild macht mir per
    Anhang mailt seit bald einem Jahr einwandfrei.


    2. Wenn ich obige Hinweise richtig verstanden habe kann mein durch einen traceback beendetes Script neu

    gestartet werden:


    a) durch Abfangen mit einer passenden Exception. Nur mit welcher Exception soll ich den folgenden traceback

    der die Probleme verursacht abfangen ?? Sehe keinen Exception Namen darin:

    Exception in thread Thread-1:

    Traceback (most recent call last):

    File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner

    self.run()

    File "/usr/lib/python2.7/threading.py", line 754, in run

    self.__target(*self.__args, **self.__kwargs)

    File "/usr/lib/python2.7/dist-packages/gpiozero/mixins.py", line 509, in fill

    self.parent._fire_events()

    File "/usr/lib/python2.7/dist-packages/gpiozero/mixins.py", line 323, in _fire_events

    self._fire_activated()

    File "/usr/lib/python2.7/dist-packages/gpiozero/mixins.py", line 301, in _fire_activated

    self.when_activated()

    File "./PIR_V4.py", line 58, in on_motion

    mail(pfad)

    File "./PIR_V4.py", line 35, in mail

    smtp = smtplib.SMTP(smtpHost, smtpPort)

    File "/usr/lib/python2.7/smtplib.py", line 256, in __init__

    (code, msg) = self.connect(host, port)

    File "/usr/lib/python2.7/smtplib.py", line 316, in connect

    self.sock = self._get_socket(host, port, self.timeout)

    File "/usr/lib/python2.7/smtplib.py", line 291, in _get_socket

    return socket.create_connection((host, port), timeout)

    File "/usr/lib/python2.7/socket.py", line 557, in create_connection

    for res in getaddrinfo(host, port, 0, SOCK_STREAM):

    gaierror: [Errno -3] Temporary failure in name resolution


    Und wenn es eine entsprechende Exception gäbe, was gebe ich im

    eingerückten Code ein ? pass?


    b) mit Hilfe von systemd und das müsste ich dann in der Konfigurations-Datei

    machen.

    Sind diese Überlegungen richtig ?

  • Link im obersten Thread

    Ich denke, du meinst oberster Post – der Link ist kaputt.

    kann mein durch einen traceback beendetes Script neu

    gestartet werden:


    a) durch Abfangen mit einer passenden Exception.

    Dann wird es gar nicht erst beendet.

    Nur mit welcher Exception soll ich den folgenden traceback

    der die Probleme verursacht abfangen ?? Sehe keinen Exception Namen darin:

    Besser hinschauen :fies:


    https://docs.python.org/3/libr…cket.html#socket.gaierror


    Das Format ist immer noch: ExceptionName: Some optional description here, dann googelst du eben "Python ExceptionName".

    Und wenn es eine entsprechende Exception gäbe, was gebe ich im

    eingerückten Code ein ? pass?

    Die gibt es, es kann ja keine Exception auftreten, die nicht existiert :-/


    pass, print(), logging.warn(), nochmal probieren, whatever...

  • Hallo luemar ,

    mir kommt so vor das die Verwendung von Exception s noch nicht so klar ist.

    Mit anschließendem Codebeispiel hoffe ich das ich dir etwas weiterhelfen kann, bzw. Licht ins Dunkle bringen kann:


    Und anstelle von prints in den except Blöcken kann man natürlich auch andere Befehle rein packen, die auf den Fehler reagieren sollen


    EDIT: Das ganze nochmals als Spoiler unformatiert, da die Formatierung als bekannten Bug die Kommentare nicht anzeigt


  • b) mit Hilfe von systemd und das müsste ich dann in der Konfigurations-Datei machen.

    Nimms mir bitte nicht übel, aber ich kann mir wirklich kaum vorstellen, dass jemand Lust hat, diesen von mir genannten Thread für Dich zu lesen, die relevanten Stellen rauszusuchen und diese dann schön mundgerecht aufbereitet zu servieren. Vergiss besser die Lösung mit Systemd.... die ist vermutlich zu einfach, als das es funktionieren kann... :evil:

  • Hallo Experten,

    nach intensiver Beschäftigung/Lernen mit/über Exceptions und systemd habe ich mein Script

    entsprechend angepasst, die Funktionen mit try und den passenden Exceptions abgesichert :https://gist.github.com/luemar…c26a0beac9fb4f4259aadefd3

    -die sms Funktion ist vorübergehend deaktiviert - und dachte ich sei jetzt am Ziel. Leider gefehlt:


    Derselbe, immer wiederkehrende traceback, in meinem Post vom 11. April 2018 aufgeführt, hat trotz Absicherung mit try und except OSError: mein Script zum Absturz gebracht. Ich war ziemlich sicher

    die richtige Exception erwischt zu haben aber evtl. steht sie am falschen Ort ?