nohup

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

    Welche Eingaben sollen ohne sudo erfolgen ?

    Alle Programme aus < ls -al /usr/bin /usr/sbin >, die ihre Ein-/Ausgabe aus dem Verzeichnis /home/USER bzw. /home/pi, oder darunter, beziehen oder beschreiben. Das betrifft auch Profil-/Konfigurations-/Script-/Autostart-/Desktop-/X-Org-Dateien. Kein Verzeichnis und keine Datei innerhalb des /home/USER/ (/home/pi) Dateibaumes darf dem User root gehören.

    Servus !

    RTFM = Read The Factory Manual, oder so

  • Bisher hatte ich im Eingabefenster nach dem Einloggen immer zuerst sudo -s

    eingegeben, hat seit ich mich mit RPi beschäftige funktioniert.

    Das ist keine gute Idee. Damit wirst du zu root und landest im Homeverzeichnis. Alle Befehle, die du eingibst werden als root ausgeführt und erstellte Dateien gehören root.

    Lass das sein und benutze sudo nur da wo es erforderlich ist. ;)

  • keepfear:

    wollte Dein "aufgeräumtes" Scripts (#3) als Basis zu einer

    Verbesserung meines Projektes benutzen, aber wenn ich

    Deine Version ausführe passiert nichts, d.h. die verschiedenen

    Funktionen und auch das Loggen finden nicht statt.

    1. Sehe ich die Ursache nicht und

    2. Ist mir die Idee hinter dem Modul functools bzw. partial nicht klar.

  • Wie startest du das Script?

    Du kannst bei einem callback:

    Code
    motion_sensor.when_motion = on_motion

    keine Argumente an die jeweilige Funktion übergeben.

    Mit partial geht das aber:

    Code
    motion_sensor.when_motion = partial(on_motion, mime,smtp, push_bullet, camera, now)

    Das erste Argument in partial ist die Funktion die du aufrufen möchtest, danach kommen die Argumente für die Funktion. Alternativ geht das auch mit lamda.

  • also ich starte das Script mit python3 onMotion_1.py und

    ich muss mich korrigieren: Dein Script funktioniert !!!

    Ich hatte es aber ergänzt (Linien 7, 22, 41, 42, 44) um vor Aufnahme des Fotos

    mittels eines Relais, über das gpiozero Modul LED, eine IR Leuchte ein- und danach

    wieder abzuschalten. Und mit dieser Ergänzung funktionierts nicht mehr:

  • Hallo,

    bitte poste immer die Fehlermeldung dazu.

    In Zeile 91wird vermutlich ein Fehler geworfen, weil es in deinem Code kein 'RELAIS_PIN' gibt. Sollte es aber, du kannst dir den 'MotionSensor' als Vorbild nehmen.

    Der Pin ist eine Konstante und erst in der 'main' wird dann der Sensor oder in deinem Fall das Relaise definiert. Das wird dann wiederum an die Funktion übergeben, die es benötigt.

    So wie jetzt ist dein Relaise global verfügbar. So etwas möchte man nicht haben, das kann ein sehr unordentliches und undurchsichtiges Programm zur Folge haben.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Vllt auch nochmal eine Erklärung.

    Alles was außerhalb der main() - Funktion steht sind Importe, Klassen, Funktionen und Konstanten.

    Konstanten werden nach Konvention immer groß geschrieben.

    Der Pin, wo dein Relais dran hängt, änderst du ja nicht mehr, wenn alles läuft. Der Pin wäre also eine Konstante.

    Besser wäre aber DigitalOutputDevice, weil du ja tatsächlich keine LED schaltest sondern dein Relais.

    Wenn du so machst, kannst du "mein_relais" als Argument der Funktion übergeben und innerhalb der Funktion damit arbeiten.

    Was zum lesen.

    https://realpython.com/python-namespaces-scope/

  • luemar

    Anmerkungen zum Quelltext: `gethostname()` aus `socket` wird importiert, aber nirgends verwendet.

    Das anlegen einer Logdatei im Programm würde ich sein lassen. Normalerweise protokolliert man einfach auf stdout oder stderr und kümmert sich darum, dass das in einer Datei landet, ausserhalb. Beispielsweise durch eine Umleitung der Ausgaben in eine Datei, oder bei systemd über die dortigen Einstellungen. Dann kann man es sich auch sparen an mehreren Stellen im Programm sowohl `print()` als auch Loggingaufrufe direkt nacheinander mit den gleichen Ausgaben zu machen. Code wiederholen ist in der Regel keine gute Idee.

    Die \ zur Zeilenfortsetzung sind überflüssig. Wenn es noch offene Klammern gibt, wo der Compiler noch nicht das schliessende Gegenstück zu jeder davon gesehen hat, ist der schon so schlau anzunehmen, dass der Ausdruck mit dem Zeilenende noch nicht vollständig sein kann.

    Ich würde das ja nicht `ralais` nennen. Den Leser interessiert ja nicht so sehr was da direkt angeschlossen ist, sondern was das für eine Bedeutung hat. Nämlich das da für das Foto noch Licht zugeschaltet wird.

    `mime` ist kein so wirklich guter Name für eine E-Mail-Nachricht.

    Weder beim Betreff noch beim Text sollte man "utf-8" als Kodierung vorgeben. Die vorhandenen Texte enthalten gar nichts was das nötig macht, und würden sie Zeichen ausserhalb von ASCII enthalten, dann wird automatisch statt mit US-ASCII mit UTF-8 kodiert.

    Die E-Mail-Nachricht wird an der falschen Stelle im Programmfluss erstellt. Einmal am Anfang, und dann wird dort *jedes* Bild angehängt, das heisst mit jedem Bild werden auch immer alle alten Bilder noch mal verschickt, weil diese eine Nachricht ja mit jedem Bild um ein weiteres Bild anwächst.

    Die Verbindung zum SMTP-Server wird auch an der falschen Stelle erstellt. Die kann ja bis ein Bild gemacht wird, mehr oder weniger beliebig lange offen sein, was aber nicht alle SMTP-Server mitmachen. Die meisten dürften nach einer gewissen Zeit ohne Aktivität von sich aus die Verbindung schliessen. Das heisst man sollte die Verbindung immer nur öffnen wenn man auch was senden will. Und dann kann man auch ``with`` verwenden und muss nicht selbst `quit()` aufrufen.

    Bei `camera` hat das `close()` in der `get_picture()`-Funktion nichts zu suchen. Das verhindert effektiv, das nach dem ersten ein weiteres Bild aufgenommen werden kann, weil das Gerät ja geschlossen wurde. `Picamera`-Objekte sind Kontextmanager können (und sollten) also mit ``with`` verwendet werden.

    `now` wird ebenfalls an der falschen Stelle im Programmfluss definiert. Beim Start des Programms und nicht wann die Bewegung tatsächlich registriert und verarbeitet wird. Da das in einer Logging-Ausgabe verwendet wird, die ja selbst schon einen Zeitstempel besitzt, macht das auch nicht so wirklich Sinn.

    das ``try``/``except KeyboardInterrupt:`` ist so wie es da steht recht sinnlos, denn der Block umfasst ja nur die beiden Zuweisungen an die `when_…`-Handler vom `MotionSensor`. Da muss das `pause()` mit drin sein. Und statt `sys.exit()` kann dann in der Behandlung einfach ``pass`` stehen, denn das Programm ist danach ja ganz ”natürlich” am Ende angelangt.

    Bei Ausnahmen würde man mindestens mal `error()` statt `info()` protokollieren, aber eigentlich will man da `exception()` verwenden, damit möglichst viele Informationen im Protokoll landen die für die Fehlersuche interessant sind.

    Was `push_sms()` zurück gibt ist sicher kein Gerät, sollte also nicht an den Namen `device` gebunden werden. Insbesondere wenn der Name vorher schon an einen anderen Wert gebunden wurde, der tatsächlich ein Gerät repräsentiert.

    In `on_motion()` würde ich noch mal ganz grundsätzlich Ausnahmen protokollieren.

    Zwischenstand (ungetestet):

    Edit: Wobei man die Ausnahmebehandlung(en) noch mal auf Sinnhaftigkeit in der aktuellen Form durchgehen muss. Denn wenn kein Bild geschossen werden konnte, sollte man auch keine E-Mail mit dem *letzten* vorhandenen Bild schicken ohne das der Benutzer das erfährt, dass das gar kein aktuelles Bild ist und das eigentlich ein Fehler aufgetreten war.

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

  • Hallo,

    sorry für die Zwischenfrage.

    __blackjack__ ich bin neulich auf 'contextlib.suppress' gestoßen und ich finde das, nach dem ich jetzt weis was das macht, lesbarer wie die Ausnahmebehandlung mit 'pass'.

    Also zum Beispiel in der aktuellen 'main' könnte man ja schreiben:

    Code
            with contextlib.suppress(KeyboardInterrupt):
                motion_sensor.when_motion = partial(
                    on_motion, push_bullet, ir_light, camera
                )
                motion_sensor.when_no_motion = on_no_motion
                pause()

    Ich schau mir ja relativ viele Codebeispiele von dir und anderen Programmierer an, aber das ist mir noch nie aufgefallen. Wieso wird das nicht benutzt?

    Dank und Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Wieso wird das nicht benutzt?

    Kennen die meisten einfach nicht.

    Genauso benutzen viele partial und lambda/Funktionen ohne zu wissen, was late-binding und early-binding für Auswirkungen haben.

  • keepfear:

    hatte einen kapitalen Fehler im Script, den relais Pin 17 falsch definiert.

    nach der Korrektur:

    kommt aber ein NameError:

    File "/home/pi/onMotion_1.py", line 41, in get_picture

    relais.on()

    NameError: name 'relais' is not defined

    obwohl relais in der Zeile 90 in main() definiert ist ???

    __blackjack__:

    ein ziemlicher Brocken zum abarbeiten für mich...

    Habe Dein Script kopiert, beim Ausführen passiert gar nichts,

    keine Fehlemeldung, keine Log Einträge ???

  • Es ist in der Funktion 'main' definiert, aber nicht in 'get_picture'. Wie geschrieben, du musst das noch übergeben. Schau dir an, was in der 'main' alles mit 'camera' gemacht wird.

    Wenn du den Code von blackjack im Terminal startest und eine Bewegung erkannt wird, dann wird im Terminal nichts ausgegeben?

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Hallo,

    dein vorherigen Code mit dem 'relais' angepasst:

    Vielleicht kannst du so erkennen, was ich gemeint habe.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

Jetzt mitmachen!

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