subprocess kontrollieren, evtl threading?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

Hallo,

beim Entwickeln meiner Django-App ist mir folgende Idee gekommen:
Krieg ich es hin, via http-Request am Heimserver die Audio-Ausgabe zu steuern?
Mein erster Ansatz in der Django-App ist:

Code: Alles auswählen

def audio(request):
    if request.POST.get("audio") == "play":
        subprocess.Popen(["play", u"/home/werner/play1.ogg"])
    return render_to_response("audio.html")
Das funktioniert auch soweit, nützt mir aber nur, wenn ich die Ausgabe wieder stoppen kann -> ich brauch Kontrolle über den subprocess. Nur: wie bekomme ich die Kontrolle beim nächsten Request? Das Objekt muss ja noch existieren, solange es "tönt"...

An Threading hab ich mich bis jetzt nicht rangetraut, denke aber, dass dies evtl ein guter Einstieg wäre??? Oder hab ich mich hier in eine Sackgasse verrannt und der Ansatz ist für die Tonne?
Zuletzt geändert von Anonymous am Samstag 8. Dezember 2012, 09:19, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Das Objekt, das noch existieren muss, wirfst du atm weg. Versuch doch mal das `Popen` Objekt zu speichern und dann schau dir an, welche Methoden das so hat.
BlackJack

@mcdwerner: Ich würde sagen dass ist mit einer Webanwendung *so* nicht machbar. Selbst das bei Dir der Ton noch weiter läuft würde ich nicht als gegeben hinnehmen sondern eher als Zufall. Webanwendungen haben einen Anfrage/Antwort-Zyklus. Alles was da nicht sicher irgendwo extern gespeichert wurde, zum Beispiel in einer Datenbank, muss beim nächsten Zyklus nicht mehr vorhanden sein. Es kann, aber es ist halt nicht garantiert.

Man könnte einen Server dafür nehmen, der garantiert ständig läuft und den von der Webanwendung aus ansprechen. Zum Beispiel den „Music Player Daemon” MPD: http://mpd.wikia.com/
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@cofi: ich war, ähnlich wie BlackJack, davon ausgegangen, dass nicht sicher ist, dass eine (globale) Variable beim 2. Request noch zur Verfügung steht, nach ein paar Versuchen scheint es zwar wie unten zu funktionieren, aber ich habe kein gutes Gefühl dabei (nicht nur wegen der globalen Variable, 2 verschiedene Requests stelle ich mir normalerweise wie 2 verschiedene Programmaufrufe vor, damit bin ich auf der sicheren Seite...)

Code: Alles auswählen

global_play = None
        
def audio(request):
    global global_play
    if request.POST.get("audio") == "play" and global_play is None:
        global_play = subprocess.Popen(["play", u"/home/werner/play1.ogg"])
    elif request.POST.get("audio") == "stop" and not global_play is None:
        global_play.terminate()
        global_play = None
    return render_to_response("audio.html")
Ich war wohl eher auf der Suche nach etwas "magischem", das garantiert beim 2. Aufruf noch existiert.
Danke dafür an BlackJack, den Zauberer ;-)
Sirius3
User
Beiträge: 17752
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo mcdwerner,

der eigentliche Zauber liegt in UNIX seit Jahrzehnten "ungenutzt", nur um für Dich für diesen Fall ausgegraben zu werden.
Das einzige was Du Dir über Deinen player merken mußt, ist die Prozess-ID.
Prozesse könne losgelöst vom Elternprozess sogar dessen Tod überleben, bis sie irgendwann gekillt werden.
Ja das Leben in der UNIX-Welt ist hart.

Hier das Beispiel:

Code: Alles auswählen

def audio(request):
    content={}
    if request.POST.get("audio") == "play":
        play = subprocess.Popen(["nohup","play", u"/home/werner/play1.ogg"])
        content['status']='playing'
        content['pid']=play.pid
    elif request.POST.get("audio") == "stop":
        os.kill(int(request.POST.get("pid")),9)
        content['status']='stopped'
    return render_to_response("audio.html",content)
 
Da Server und Player jetzt völlig unabhängig voneinander laufen, steht
Deiner Smartphone-Fernbedienung jetzt nichts mehr im Wege.

Grüße
Sirius

PS: VORSICHT!!!!
pid sollte noch irgendwie auf Richtigkeit geprüft werden, wer weiß welche Prozesse sonst noch abgeschossen werden.
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@Sirius3: auf die Idee, die pid um die hlabe Welt (naja gut durchs ganze Haus...) zu schicken wäre ich im ersten Moment auch nicht gekommen, nur was mache ich, wenn die unterwegs verloren geht? Besser ich speichere sie zusätzlich noch in der Datenbank, sonst kann ich nur warten bis der Prozess von alleine endet oder muss mich ans Terminal setzen und den Prozess von Hand killen...

Jedenfalls vielen Dank für die Denkanstöße!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Noch besser du nutzt einfach wie BlackJack angemerkt hat MPD, dann kannst du den ganz einfach kontrollieren. Sogar Webinterfaces gibt es zu MPD schon.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@Leonidas: es gibt sogar schon was für Django: https://github.com/mklauber/django-mpd-client :D
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Na da siehst du mal, lauter gute Gründe für MPD. 8)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten