Aus Master Python Script ein Slave Python Script aufrufen

  • Hallo zusammen,

    mit diesem

    wird mit der Funktion record_video ein 10 sec. Video im Format h264 aufgenommen und im Ordner /home/ich-bins/ gespeichert.

    Die Funktion transfer überträgt das h264-Video per FTP in ein NAS.

    Die Funktion change_video_format erzeugt aus dem h264-Video ein mp4-Video und speichert es im Ordner /home/ich-bins/.

    Die Funktion h264_entfernen löscht das h264-Video im Ordner /home/ich-bins/.

    Der Transfer des 10 Sekunden h264 Videos und das anschließende Wandeln in das mp4-Format dauern zusammen ca. 11 Sekunden. Erst danach ist eine weitere Aktion möglich.

    Kann man die Funktion transfer und die Funktion change_video_format ein zweites Script auslagern und im ersten Script nach der Funktion record_video starten, so dass im ersten Script sofort wieder die nächste Video-Aufnahme gestartet werden kann?

    Viele Grüße

    Ich Bins

  • Aus Master Python Script ein Slave Python Script aufrufen? Schau mal ob du hier fündig wirst!

  • Also ich würde den ProcessPoolExecutor einsetzen.

    Den angepassten Code musst du testen.


    Die Funktion transfer hat es nach dem Code-Formatting (black) etwas "zerrissen".

    Man kann Context-Manager auch verschachteln.

    Seit Python 3.9 kann man runde Klammern nutzen und bei Python 3.10 wird es offiziell unterstützt (wegen dem neuen Parser).

    Vor Python 3.9 (Verschachteln)

    Code
    def transfer(video_file):
        new_video_file = video_file.with_suffix(VIDEO_FORMAT[0])
        with FTP("192.168.178.1", "Ich-Bins", "Password") as ftp:
            with open(new_video_file, "rb") as file:
                ftp.storbinary(f"STOR {new_video_file.name}", file)

    Python 3.9+

    Code
    def transfer(video_file):
        new_video_file = video_file.with_suffix(VIDEO_FORMAT[0])
        with (
            FTP("192.168.178.1", "Ich-Bins", "Password") as ftp,
            open(new_video_file, "rb") as file,
        ):
            ftp.storbinary(f"STOR {new_video_file.name}", file)

    Der Nachteil beim neuen Code ist, dass der Code-Formatter black damit nicht umgehen kann, da dieser noch den alten LL(1) Parser nutzt. Erst wenn der neue PEG-Parser in black implementiert ist, kann black auch solche Strukturen parsen.

    Bis mal Python 3.10 bei Raspberry Pi OS verfügbar ist, werden noch zwei Releases vergehen müssen.

    Ich meine 3.9 wird bei Debian 11 verwendet. Einer der vielen Gründe, wieso ich Debian für Entwicklung nicht mag.

    Edit:

    Exceptions, die in der Funktion task ausgelöst werden, sind nicht im Programm sichtbar und gehen einfach unter.

    pool.submit(funktion) gibt ein Future zurück und ob eine Exception aufgetreten ist, kann man mit fut.exception() prüfen. Es wird einem dann die Exception als Objekt zurückgegeben. Vorteilhaft ist, dass man die Funktion task auch ohne den ProcessPoolExecutor testen kann.

    2 Mal editiert, zuletzt von RestlessMud46765 (16. Oktober 2021 um 20:00) aus folgendem Grund: 3. h264_entfernen in Funktion task ausführen. flush=True zu den print Funktionen hinzugefügt. Edit2: Funktion change_video_format new_video_file str

  • Hallo DeaD_EyE,

    vielen Dank.

    Wenn ich das Script richtig interpretiere werden die Funktionen transfer und change_video_format jetzt in der Funktion task aufgerufen und nicht mehr in der Funktion main.

    In das komplette Script habe ich vor dem Starten sleep auf 300 erhöht.

    Beim Starten erhalte ich im Terminal

    Start Video-Aufnahme - 20211015-184409

    Ende Video-Aufnahme - 18:44:19

    Nach etwas mehr als einer Minute stoppte ich das Script.

    Im Ordner home/ich-bins/motioneye/Camera1 wird kurz ein h264-Video gespeichert und gleich danach entfernt. Ein mp4-Video wird nicht erzeugt.

    Im NAS kommt das h264-Video nicht an.

    Starte ich erneut erhalte ich im Terminal

    mmal: mmal_vc_port_enable: failed to enable port vc.null_sink:in:0(OPQV): ENOSPC

    mmal: mmal_port_enable: failed to enable connected port (vc.null_sink:in:0(OPQV))0x703090 (ENOSPC)

    mmal: mmal_connection_enable: output port couldn't be enabled

    Backend terminated or disconnected. Use 'Stop/Restart' to restart.

    Ohne einen Reboot geht in Thonny nichts mehr.

    Beim erneuten Starten und Beenden gleiches Spiel wie bereits beschrieben. Wenn ich jedoch das Script nicht beende erhalte ich im Terminal

    Start Video-Aufnahme - 20211015_191534

    Ende Video-Aufnahme - 19:15:44

    Start Video-Aufnahme - 20211015_192044

    Ende Video-Aufnahme - 19:20:54

    Start Video-Aufnahme - 20211015_192555

    Ende Video-Aufnahme - 19:26:05

    Start Video-Aufnahme - 20211015_193105

    Ende Video-Aufnahme - 19:31:15

    Für mich als Python-Laie sieht es so aus, wie wenn die Funktionen transfer und nicht gestartet wird

    und die Funktion change_video_format beim manuellen Beenden die picamera blockiert.

    Kann es sein, dass die neuen Variablen h264_video und mp4_video nicht korrekt übergeben werden?

    Viele Grüße

    Ich Bins

  • Habe ich mal korrigiert. Auch der Fakt, dass Exceptions nicht ausgelöst, sondern übertragen werden, ist wichtig.

    Wenn man irgendwo im Code einen Fehler hat und das nicht prüft, geht der Fehler einfach unter und man bekommt keine Rückmeldung, was falsch lief.

    Eine zusätzliche Möglichkeit ist es noch einen done_callback hinzuzufügen:

    Man kann die Funktion, die die anderen zusammenfasst, mal ohne den pool aufrufen und dann ist das alles wieder seriell.

  • Hallo DeaD_EyE,

    nach dem hoffentlich richtigen Einfügen Deiner Korrektur wurde die Datei 20211016_134901.h264 erstellt aber gleich wieder gelöscht und ich erhalte diese Meldung.

    Start Video-Aufnahme - 20211016_134901

    Ende Video-Aufnahme - 13:49:11

    Ausnahmefehler: [Errno 2] No such file or directory: '/home/ich-bins/motioneye/Camera1/20211016_134901.h264'

    Aktueller Zustand:

  • Ich habe die Funktion task im Beitrag korrigiert.

    Das Problem wird gewesen sein, dass die originale Datei gelöscht worden ist, bevor sie überhaupt übertragen/umgewandelt werden konnte.

    Wenn unter Linux Dateien geöffnete Dateien "gelöscht" werden, kann der Prozess, der die Datei gerade offen hat, weiter auf die Datei zugreifen. Die Datei kann aber nach dem Löschen nicht erneut geöffnet werden, da der Eintrag nicht mehr sichtbar ist. Das wird oft als Sicherheitsfeature verwendet, wenn andere neugierige Prozesse nicht auf eine Datei zugreifen sollen. Im Fall des Scriptes war es wahrscheinlich so, dass er gerade eben noch den Transfer starten konnte, wodurch die Quelldatei zumindest erstellt worden ist. Nebenläufig dazu hat er schon direkt die nächste Funktion im der Hauptschleife ausgeführt, die die Quelldatei löschen sollte. Zu diesem Zeitpunkt find das Transkodieren noch gar nicht an.

    Nebenläufiger Code kann ziemlich komplex werden und schwer zu debuggen.

    Bitte auch beachten, dass pool.submit() nicht blockiert, solange noch genügend worker frei sind. D.h. der Task wird übermittelt und er macht direkt mit dem nächsten Statement weiter.

  • Nach dieser Änderung wird das h264-Video ins NAS übertragen.

    Video-Aufnahme - 20211016_183912

    Ende Video-Aufnahme - 18:39:22

    Übertragung von /home/ich-bins/motioneye/Camera1/20211016_183912.h264 abgeschlossen

    Übertragung von /home/ich-bins/motioneye/Camera1/20211016_183912.h264 abgeschlossen

    Die Funktion change_video_format stolpern über irgendwas.

    [Importer] Unknown input file type for "/home/ich-bins/motioneye/Camera1/20211016_183912.mp4"

    [Importer] Unknown input file type for "/home/ich-bins/motioneye/Camera1/20211016_183912.mp4"

    Error importing /home/ich-bins/motioneye/Camera1/20211016_183912.mp4: Requested URL is not valid or cannot be found

    Error importing /home/ich-bins/motioneye/Camera1/20211016_183912.mp4: Requested URL is not valid or cannot be found

    Ausnahmefehler: Command '['MP4Box', '-fps', '30', '-add', PosixPath('/home/ich-bins/motioneye/Camera1/20211016_183912.mp4'),

    PosixPath('/home/ich-bins/motioneye/Camera1/20211016_183912.mp4')]' returned non-zero exit status 1.

    (Die Zeilen wurden teilweise doppelt ausgegeben)

    Das h264-Video wird danach nicht entfernt.

  • Der Fehler tritt in der Funktion change_video_format auf. Das Pfad-Objekt new_video_file muss in ein str umgewandelt werden, da ansonsten für die Argumentenliste die Repräsentation des Pfandobjektes verwendet wird.

    Dem Programm MP4Box würde dann mit dem Pfad PosixPath('/home/ich-bins/motioneye/Camera1/20211016_183912.mp4') aufgerufen werden, was offensichtlich falsch ist. Wenn man str auf ein Path-Objekt anwendet, bekommt man den Pfad als str zurück. Das muss man ziemlich oft machen, wenn man die Pfade an andere Funktionen übergibt, die z.B. damit noch nicht umgehen können oder nicht dafür vorgesehen sind.

  • Hallo,

    Kann man die Funktion transfer und die Funktion change_video_format ein zweites Script auslagern und im ersten Script nach der Funktion record_video starten, so dass im ersten Script sofort wieder die nächste Video-Aufnahme gestartet werden kann?

    du willst dass die zwei Funktionen ausgeführt werden, während dein Programm etwas anderes macht. Dabei kam mir gleich ein älteres Thema von dir in den Kopf. Ich hätte dass evenuell wie hier gelöst und würde dann zu diesem Ergebnis kommen:

    Jetzt bitte nicht die Idee von @DeaD_EyE verwerfen, die ist alleine wegen der Fehlerbetrachtung schon besser.

    Wollte dir nur zeige dass du eine mögliche Lösung schon hattest.

    Grüße

    Dennis

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

  • Wenn du du ein Objekt in einen String umwandeln willst, dann nutzt man str().

    Wenn du einfach video_file in Anführungszeichen setzt, dann fehlt dir das Pfad-Objekt, dass an den Namen 'video_file' gebunden wurde und du hast einen String 'video_file'.

    Hier ein Beispiel:


    Lass das mal laufen, kannst du dass dann nachvollziehen?

    Grüße

    Dennis

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

  • Hallo Dennis,

    stimmt Du hast recht, mit Deiner Thread Lösung wurde Wasser marsch und Video-Aufnahme parallel möglich.

    Habe es jedoch in diesem Zusammenhang nicht mehr auf dem Schirm gehabt.

    Dieses Script möchte ich auch erweitern, zur besseren Übersichtlichkeit habe ich für diese Anfrage PIR und Wasserwerfer aus dem Script entfernt.

  • Hallo Dennis,

    auch nach Deinen verständlichen Beispielen ist die Erstellung des mp4-Videos gescheitert.

    Das Pfad-Objekt new_video_file muss in ein str umgewandelt werden

    An zwei für mich sinnvoll erscheinenden Positionen habe ich str eingesetzt und erhielt wieder Fehlermeldungen.

    Erste Variante.

    Zweite Variante.

  • Hallo,

    mich wundert dass das mit den Pfad-Objekten nicht funktioniert, wobei der Code so wie er ursprünglich war ja schon funktioniert hat.

    Ich habe mir den Code aus Beitrag 3 angeschaut und ihn als Grundlage genommen.

    Dort wird der Funktion 'change_video_format' nicht die ursprüngliche Video-Datei mit dem zu ändernden Format übergeben, sondern schon die die noch gar nicht existiert.

    Hab das mal kommentiert und abgeändert. Hoffe ich erzähl hier gerade kein Mist :blush:

    Grüße

    Dennis

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

  • Hallo Dennis, hallo DeaD_EyE,

    vielen herzlichen Dank für Eure Hilfe.

    Hatte ich "blindes Huhn" etwa ganz unten im vierten Beitrag so eine Vorahnung?

    Kann es sein, dass die neuen Variablen h264_video und mp4_video nicht korrekt übergeben werden?

    Jetzt funzt es eigentlich. Nachdem ich die Pause am Ende auf eine Sek. reduziert habe ist vermutlich das eingetreten was ich befürchtet hatte.

    Wenn das nächste Video bereits aufgenommen wird bevor transfer und change_video_format fertig sind kommt der gesamte Prozess außer Tritt.

    Die h264-Videos werden laufend erzeugt sind aber nicht mehr mind. 20 Mb groß sondern einige Mb kleiner. So wie es aussieht werden alle h264-Videos ins NAS kopiert und auch alle mp2-Videos erzeugt obwohl einige Ausnahmefehler im Terminal ausgegeben werden. Die Videos sind auch okay.


    Ausschnitt aus dem Terminal-Protokoll

    /home/ich-bins/motioneye/Camera1/20211017_123128.mp4

    Transkodierung abgeschlossen

    Original /home/ich-bins/motioneye/Camera1/20211017_123118.h264 entfernt

    Transkodierung abgeschlossen

    Original /home/ich-bins/motioneye/Camera1/20211017_123128.h264 entfernt

    Ausnahmefehler: [Errno 2] No such file or directory: '/home/ich-bins/motioneye/Camera1/20211017_123128.h264'

    Transkodierung abgeschlossen

    Ausnahmefehler: [Errno 2] No such file or directory: '/home/ich-bins/motioneye/Camera1/20211017_123047.h264'

    Ende Video-Aufnahme - 12:32:59

    Start Video-Aufnahme - 20211017_123259

    Übertragung von /home/ich-bins/motioneye/Camera1/20211017_123118.h264 abgeschlossen

    /home/ich-bins/motioneye/Camera1/20211017_123118.mp4

    Cannot find file /home/ich-bins/motioneye/Camera1/20211017_123118.h264

    Error importing /home/ich-bins/motioneye/Camera1/20211017_123118.h264: Requested URL is not valid or cannot be found

    Ausnahmefehler: Command '['MP4Box', '-fps', '30', '-add', PosixPath('/home/ich-bins/motioneye/Camera1/20211017_123118.h264'), PosixPath('/home/ich-bins/motioneye/Camera1/20211017_123118.mp4')]' returned non-zero exit status 1.

    Ende Video-Aufnahme - 12:33:09

    Start Video-Aufnahme - 20211017_123309

    Ende Video-Aufnahme - 12:33:19

    Start Video-Aufnahme - 20211017_123319

    Übertragung von /home/ich-bins/motioneye/Camera1/20211017_123149.h264 abgeschlossen

    /home/ich-bins/motioneye/Camera1/20211017_123149.mp4

    AVC-H264 import - frame size 1920 x 1080 at 30.000 FPS

    Importing AVC-H264: | | (01/100)

    Importing AVC-H264: | | (02/100)

    Importing AVC-H264: | | (03/100)

    Importing AVC-H264: | | (04/100)

    Importing AVC-H264: |= | (05/100)

    Importing AVC-H264: |= | (06/100)

    Übertragung von /home/ich-bins/motioneye/Camera1/20211017_123139.h264 abgeschlossen

    /home/ich-bins/motioneye/Camera1/20211017_123139.mp4

    Importing AVC-H264: |= | (07/100)

    So extrem wird es im Wirkbetrieb nicht ablaufen.

    Nachdem ich jetzt 200 Sek. Pause eingefügt habe werden seltsamerweise wieder Ausnahmefehler

    PosixPath('/home/ich-bins/motioneye/Camera1/20211017_123118.mp4')]'

    gemeldet aber es läuft ohne ersichtliche Fehler weiter.

    Jetzt habe ich str(new_video_file) getestet. Danach erhalte ich jedoch noch hin und wieder diesen Ausnahmefehler und ständig

    Cannot find file /home/ich-bins/motioneye/Camera1/20211017_132110.h264

    Error importing /home/ich-bins/motioneye/Camera1/20211017_132110.h264: Requested URL is not valid or cannot be found

    Jetzt muss ich erst mal den Wirk-String ergänzen und testen.

    Viele Grüße

    Ich Bins

  • Im Wirkbetrieb verursacht die Version von DeaD_EyE und ebenfalls die Version von Dennis ununterbrochen PIR-Bewegungserkennung.

    Ich kann mir das nur so erklären, dass die parallelen Prozesse Schwankungen oder Störungen in der gemeinsamen Stromversorgung verursachen und dadurch die PIR verrückt spielen. Alles hängt an dem original PI-Netzteil.

    Ich gehe davon aus, dass bei beiden Versionen Transfter ins NAS und Erzeugung des mp4-Videos zur selben Zeit ablaufen.

    Wie kann man diese beiden Funktionen hintereinander starten?

  • Kannst du bitte den aktuellen vollständigen Code posten? Dann bleiben wir bei einer Version. Da DeaD_EyE wesentlich mehr Erfahrung hat, würde ich seinen Code bevorzugen.

    Dann können wir mal alles einheitlich aufbauen :thumbup:

    Grüße

    Dennis

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

  • Bei der ProcessPoolExecutor Variante erhalte ich beim erneuten Versuch das Script zu starten diese Meldung. Damit ich es erneut starten kann muss ich den PI neu starten. Das ist mir bereits beim Testen (Beitrag 4) aufgefallen.

    mmal: mmal_vc_port_enable: failed to enable port vc.null_sink:in:0(OPQV): ENOSPC

    mmal: mmal_port_enable: failed to enable connected port (vc.null_sink:in:0(OPQV))0x703090 (ENOSPC)

    mmal: mmal_connection_enable: output port couldn't be enabled


    Backend terminated or disconnected. Use 'Stop/Restart' to restart.

    Hier ist der Wirk-Code mit der ProcessPoolExecutor Variante.

Jetzt mitmachen!

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