App über skript steuern

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
Benutzeravatar
mobby
User
Beiträge: 76
Registriert: Donnerstag 17. April 2014, 09:43

Hey Leute,

stehe wieder vor einem Problem. Dabei geht es darum, dass ich eine app aufrufe, der ich meine gewünschte Funktion leider nicht als Argument übergeben kann, sondern sobald das Programm gestartet ist, es Operatoren gibt, um Aufgaben zu triggern. Das bedeutet im Klartext, wenn ich das Programm z.B. über die Konsole starte, erscheint nach mini lagg ein Menü, in dem ich mit Buchstabeneingaben, z.B. "R", Aufgaben triggern kann. Wie kann ich das jetzt über mein Skript erledigen? Ich habe einen Ansatz vorbereitet, funktioniert aber nicht.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import subprocess
from time import sleep


def trigger_task():
    app = subprocess.Popen(["/home/pi/app", "-c", "USB"], stdin=PIPE) #so starte ich die app
    sleep(1)
    app.communicate(input="R") #mein Versuch den operator "R" auszuführen
    sleep(1)
    app.terminate()


def main():
    trigger_task()


if __name__ == '__main__':
    main()
Die Doku sagt mir:

Popen.communicate(input=None)
Interact with process: Send data to stdin.

Note that if you want to send data to the process’s stdin, you need to create the Popen object with stdin=PIPE.


Mein Fehler dabei ist, dass ich das Thema "PIPE" einfach nicht verstehe und das trotz durchlesen der Doku. Kann mir da bitte jemand auf die Sprünge helfen? Vor allem, ist der Ansatz hier sonst richtig oder liege ich komplett falsch?

Vielen Dank für Feedback!

Gruß
mobby
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Hi,

kann es sein, dass deine App eine "ENTER" (\n) erwartet?

Code: Alles auswählen

app = subprocess.Popen(["/home/pi/app", "-c", "USB"], stdin=PIPE)
app.communicate("R\n")
Grüße
Gerrit
BlackJack

@mobby: `communicate()` wartet bis das externe Programm beendet ist. Es macht also weder Sinn danach zu warten, noch den bereits beendeten Prozess zu beenden. Vorher zu warten ist normalerweise auch nicht nötig es sei denn man kann am Anfang 'R' senden und das führt zu einem Fehler beim externen Programm.

Wenn Du 'R' an das laufende Programm senden und dann eine Sekunde warten willst, bevor Du es ”gewalttätig” beendest, musst Du den Buchstaben in `stdin` von dem Prozess schreiben, und die Ausgabe ”flushen”, damit die tatsächlich rausgeschrieben wird.

Code: Alles auswählen

def trigger_task():
    app = Popen(['/home/pi/app', '-c', 'USB'], stdin=PIPE)
    app.stdin.write('R')
    app.stdin.flush()
    sleep(1)
    app.terminate()
Eventuell gilt das von gkuhl gesagte zum Zeilenendezeichen.

Sollte das nicht gelten, kann es auch sein, dass das externe Programm gar nicht über eine Pipe steuerbar ist, nämlich wenn es zwingend ein Terminal erwartet um Benutzereingaben entgegen zu nehmen. Dann muss man dem Programm vorspiegeln es sei mit einem Terminal verbunden. Bevor man da selber in das Thema Pseudoterminals einsteigt, bietet sich dafür das `pexpect`-Modul an.
Benutzeravatar
mobby
User
Beiträge: 76
Registriert: Donnerstag 17. April 2014, 09:43

@BlackJack: Vielen Dank für die Tips! Kann ich leider erst Anfang nächster Woche ausprobieren, aber sieht schon mal gut aus. Ich melde mich, ob es funktioniert.
Antworten