Seite 1 von 1

Frage an die Experten - Subprozess mit "tee"

Verfasst: Mittwoch 25. März 2015, 19:42
von mcbo
Hallo,

ich habe mir mit einem Raspberry Pi (Linux), einem DVB-T Stick
und ein bisschen Python :wink: einen Funkdecoder gebaut.

Momentan funktioniert folgender Codeschnippsel:

Code: Alles auswählen

multimon_ng = subprocess.Popen("rtl_fm -d 0 -f XXX.XXXM -M fm -s 22050 -l 0 -p 5 -E DC -F 0 -g 40 | multimon-ng -a POCSAG512 -f alpha -t raw /dev/stdin",
                               stdout=subprocess.PIPE,
                               stderr=open(LogString_multimonng,'a'),
                               shell=True)

try:
    while True:

        line = multimon_ng.stdout.readline()
        multimon_ng.poll()
       
        # ab hier wird decodiert
Momentan wird der Audiostream des DVB-T-Sticks direkt in den Decoder (multimon_ng) gespeist.
Ich würde das Audiosignal aber gerne abgreifen und zusätzlich auf einen Lausprecher geben.
Das funktioniert in der Command Line ohne Probleme so:

Code: Alles auswählen

rtl_fm -d 0 -f XXX.XXXM -M fm -s 22050 -l 15 -p 5 -E DC -F 0 -g 40 | tee >(multimon-ng -a POCSAG512 -f alpha -t raw /dev/stdin) >(AUDIODEV=plughw:3,0 play -t raw -r 22050 -e signed-integer -b 16 -c1 -V1 -q -) > /dev/null
Leider bekomme ich das so nicht als Subprozess im Pythonscript zum Laufen.
Das Script läuft dann ohne Fehlermeldung mit 100% CPU-Last, funktioniert aber nicht.

Ich habe es schon mit einem zweiten Subprozess probiert. (stdin=rtl_fm.stdout)
Dann ist das Timing aber so lang, das kein vernünftiges Audio-Signal mehr raus kommt.


Kann mir dabei jemand helfen?


Danke


Gruß

Marcel

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Mittwoch 25. März 2015, 22:24
von BlackJack
@mcbo: Was soll beim ersten Quelltext der `poll()`-Aufruf bewirken? Der macht keinen Sinn.

Statt der ”Endlos”-``while``-Schleife und dem `readline()`-Aufruf würde sich eine ``for``-Schleife über das Dateiobjekt anbieten.

Dateien die man öffnet sollte man auch wieder schliessen. Bei der Logdatei für die Standardfehlerausgabe verlässt Du Dich hingegen darauf das das die automatische Speicherbereinigung irgendwann tun wird. Oder das Prozessende.

Warum verwendest Du bei ``multimon-ng`` ``/dev/stdin`` statt ``-`` als Dateiname?

Die ``>(…)``-Shell-Syntax ist AFAIK eine Bash-Geschichte, die wird ``/bin/sh`` wahrscheinlich nicht verstehen.

An der Stelle Frage ich mich dann aber sowieso wieso überhaupt Python wenn man damit solche Shell-Ungetüme ausführt.

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Donnerstag 26. März 2015, 21:15
von mcbo
Hi,

Sorry ich habe Dir nur Auszüge aus meinem Python Script präsentiert.

Das Script wird einmal gestartet und soll dann in einer Endlosschleife (24h/365Tage) die Konsolenausgabe vom Dekoder "multimon-ng"
abfischen, verarbeiten und in eine MySQL-Tabelle schreiben.

Mein Script habe ich an diesem angelehnt und erweitert.
https://gist.github.com/th0ma5w/8622962

Wie gesagt es läuft, ich wollte den Datenstream nur noch einmal abgreifen und das macht mir Probleme.
An der Stelle Frage ich mich dann aber sowieso wieso überhaupt Python wenn man damit solche Shell-Ungetüme ausführt.
Weil Python eine einfache Programmiersparche mit sehr vielen Modulen ist.

Gruß

Marcel

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Freitag 27. März 2015, 07:43
von EyDu
mcbo hat geschrieben:Das Script wird einmal gestartet und soll dann in einer Endlosschleife (24h/365Tage) die Konsolenausgabe vom Dekoder "multimon-ng"
abfischen, verarbeiten und in eine MySQL-Tabelle schreiben.
Das ändert ja aber nichts daran, dass das mit einer for-Schleife über ``multimon_ng.stdout`` in diesem Fall schöner geht. Da ist das readline gleich mit eingebaut.

Code: Alles auswählen

for line in mutlimon_ng.stdout:
    ...
Wo genau wird denn bei dir die Rechenzeit verbraten? Hast du mal einen Profiler laufen lassen? Dann spart man sich das Raten.

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Freitag 27. März 2015, 08:30
von BlackJack
@mcbo: Ob Python eine einfache Programmiersprache ist, da kann man trefflich drüber streiten. :-) Die Frage bleibt aber, denn wenn ich in Python programmiere und der Hauptteil des Programms aus einem komplizierten Shell-Konstrukt besteht, statt aus Python-Code, dann programmiere ich ja nicht wirklich in Python. Man kann die letztendliche Auswertung der Ausgabe ja in Python schreiben und dass dann in einem Shell-Skript am Ende der Pipes aufrufen. Dann hat man auch Kontrolle darüber mit *welcher* Shell der Shell-Anteil ausgeführt wird. Wie gesagt das ``>(…)`` wird so nicht funktionieren weil die `dash` das nicht kennt.

Das verlinkte Skript scheint mir nicht von jemandem geschrieben worden zu sein der Python kann. Da sind ein paar komische bis unschöne Sachen drin. Und handfeste Fehler.

Wenn man einen ``lambda``-Ausdruck an einen Namen bindet, dann möchte man gar keinen ``lambda``-Ausdruck sondern eine ganz normale Funktionsdefinition. Denn einer anonymen Funktion einen Namen zu geben ist widersinnig.

Bei beiden externen Prozessen ist es unnötig eine Shell zu starten. Das sind bloss zwei *zusätzliche* Prozesse die jeweils zwischen dem Programm und dem jeweiligen externen Prozess sitzen.

Bei beiden externen Prozessen wird die Standardfehlerausgabe ”gepiped” — aber dann wird damit überhaupt nichts gemacht. Sollte auch nur einer der beiden Prozesse dort tatsächlich etwas ausgeben, dann bleibt das alles hängen sobald der Puffer der Pipe voll ist und macht nichts mehr bis man es abbricht. Das ist eindeutig ein Fehler.

Der im Kommentar sogenannte ``try``/``catch``-Hack ist vor allem ein solcher weil *jede* Ausnahme mit einem ``except: pass`` ”behandelt” wird, statt genau die eine Ausnahme dort gezielt zu verarzten die ein Strg+C auslöst. Und *das* wäre dann auch kein ”hack” sondern genau die vorgesehene Methode diese Situation zu verarbeiten.

Das man über die `stdout`-Datei iterieren kann und dass der `poll()`-Aufruf keinen Sinn macht, hatte ich ja schon geschrieben.

`__contains__` ruft man nicht direkt auf. Dafür ist der ``in``-Operator da. Der Test ist allerdings nicht robust weil man ja gar nicht wissen möchte ob irgendwo innerhalb der Zeile 'Alpha:' vorkommt, sondern ob die Zeile mit 'POCSAG512: Alpha: ' *anfängt*. Und diese Zeichenkette sollte man dann auch nicht zum ”aufteilen” benutzen, denn man möchte ja nicht zwei Teile an dieser Zeichenkette trennen, sondern alles *nach* diesem Präfix haben. Das sollte man dann aber auch genau so ausdrücken.

Wenn man das in Python lösen möchte, ohne eine Unix-Shell, dann müsste man die Funktionalität von ``tee`` selber implementieren, also drei Prozesse starten (``rtl_fm``, ``multimon_ng``, und ``play``) und die Standardausgabe von ``rtl_fm`` auslesen und in die Standardeingabe von den beiden anderen Prozessen schreiben. Eventuell mit Hilfe eines zusätzlichen Threads damit da nichts blockiert.

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Freitag 27. März 2015, 15:51
von mcbo
Danke erst einmal für Eure Infos.
Da ich mich erst seit kurzem mit Python befasse, ist das erst einmal sehr viel Stoff :roll:
EyDu hat geschrieben:Das ändert ja aber nichts daran, dass das mit einer for-Schleife über ``multimon_ng.stdout`` in diesem Fall schöner geht. Da ist das readline gleich mit eingebaut.
Ich habe jetzt testweise mal "while True:" durch "for line in multimon_ng.stdout:" ersetzt und das Script sehr stark bereinigt.

Damit bekomme ich aber keine Ausgabe.
Mit der while Schleife läuft es. Was mache ich falsch :K

Code: Alles auswählen

multimon_ng = subprocess.Popen("rtl_fm -d 0 -f XXX.XXXM -M fm -s 22050 -l 0 -p 11 -E DC -F 0 -g 50 | multimon-ng -a POCSAG512 -f alpha -t raw -",
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            shell=True)
 

try:
    for line in multimon_ng.stdout:
        print line

except:
    pass

multimon_ng.kill() 
@BlackJack

Wie kann ich den Ausgabestream von meinem "multimon-ng", vom Bash an ein Python-Script übergeben und permanent auswerten?



Danke

Gruß

Marcel

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Freitag 27. März 2015, 16:14
von BlackJack
@mcbo: Da sollte man eigentlich eine Ausgabe bekommen, keine Ahnung was falsch läuft. Steht da vielleicht tatsächlich 'XXX.XXXM' als Frequenz in Deinem Programm und ``rtl_fm`` produziert schon keine Ausgabe? Oder vielleicht eine *Fehlermeldung* auf der *Fehler*ausgabe die umgeleitet aber nicht ausgelesen wird und da passiert jetzt das was ich beschrieben hatte: die ganze Sache hängt weil der Puffer voll ist.

Wenn man ein Programm schreibt das nur die Ausgabe vom ``multimon_ng`` auswerten soll, dann hängt man das einfach in der Shell per Pipe hinten dran und liest die Standardeingabe (`sys.stdin`) und wertet die aus. Ist ein Dateiobjekt, man kann dort also in einer ``for``-Schleife über die Zeilen iterieren.

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Freitag 27. März 2015, 23:39
von mcbo
BlackJack hat geschrieben:Steht da vielleicht tatsächlich 'XXX.XXXM' als Frequenz in Deinem Programm und ``rtl_fm`` produziert schon keine Ausgabe? Oder vielleicht eine *Fehlermeldung* auf der *Fehler*ausgabe die umgeleitet aber nicht ausgelesen wird und da passiert jetzt das was ich beschrieben hatte: die ganze Sache hängt weil der Puffer voll ist.
Ne, habe einfach den while Part ausgetauscht. Komisch.
Wenn man ein Programm schreibt das nur die Ausgabe vom ``multimon_ng`` auswerten soll, dann hängt man das einfach in der Shell per Pipe hinten dran und liest die Standardeingabe (`sys.stdin`) und wertet die aus.
Danke, damit hast Du mir sehr geholfen.
Habe mein Programm jetzt umgebaut und rufe es von der "tee Pipe" aus dem Bash auf.
Aber auch hier funktioniert nur die while Schleife und nicht die for Schleife.

Gruß

Marcel

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Samstag 28. März 2015, 07:13
von snafu
Warum nicht einfach so:

Code: Alles auswählen

output = multimon_ng.communicate()[0]
Oder alternativ check_output() benutzen.

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Samstag 28. März 2015, 09:52
von BlackJack
@snafu: Weil die Ausgabe live ausgewertet werden soll und das 24/7 durchgehend läuft, es also kein Prozessende gibt bei dem dann die gesammelten Ausgaben zurückgegeben werden.

Re: Frage an die Experten - Subprozess mit "tee"

Verfasst: Samstag 28. März 2015, 10:55
von snafu
Ok, so detailliert hatte ich nicht gelesen.