2017-09-16 4 views
2

Ich suche nach interface mit einer interaktiven Kommandozeilen-Anwendung mit Python 3.5. Die Idee ist, dass ich den Prozess am Anfang des Python-Skripts starte und offen lasse. In einer Schleife drucke ich einen Dateipfad, gefolgt von einer Zeilenrückgabe, an stdin, warte eine viertel Sekunde oder so während der Verarbeitung und lese von stdout, bis es eine neue Zeile erreicht.Python-Subprozess: Druck auf stdin, lese stdout bis newline, wiederhole

Dies ist ziemlich ähnlich zu der communicate Funktion von subprocess, aber ich warte auf eine Zeilenrückgabe statt warten auf den Prozess zu beenden. Wer ist sich einer relativ einfachen Möglichkeit bewusst, dies zu tun?

Edit: Es wäre vorzuziehen, die Standardbibliothek zu verwenden, um dies zu tun, anstatt Bibliotheken von Drittanbietern wie pexpect, wenn möglich.

+4

Haben Sie sich das 'pexpect' Modul angeschaut? –

+0

@ JonClements Ich habe es zuvor für SSH verwendet. Dafür werde ich jedoch nachsehen. Vielen Dank! –

+0

noch ... benutz 'pexpect'. Es gibt gazillion Komplikationen, weshalb die Verwendung von Standard-Bibliothek nicht empfohlen werden kann. –

Antwort

2

Sie können dafür subprocess.Popen verwenden.

Etwas wie folgt aus:

proc = subprocess.Popen(['my-command'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 

Jetzt proc.stdin und proc.stdout sind Ihre Enden der Rohre, die Daten an die subprocess stdin und lesen aus dem subprocess stdout senden.

Da Sie nur Zeilen mit Zeilenvorschub lesen möchten, können Sie Probleme durch Pufferung vermeiden. Die Pufferung ist einer der großen Fehler, wenn Subprozess zur Kommunikation mit interaktiven Prozessen verwendet wird. Normalerweise ist I/O line-gepuffert, was bedeutet, dass, wenn der Subprozess keine Zeile mit newline beendet, Sie niemals Daten unter proc.stdout sehen werden und umgekehrt, wenn Sie an proc.stdin schreiben - es sieht es vielleicht nicht, wenn Sie es sind nicht mit Newline enden. Sie können die Pufferung ausschalten, aber das ist nicht so einfach und nicht plattformunabhängig.

Ein anderes Problem, das Sie möglicherweise lösen müssen, besteht darin, dass Sie nicht feststellen können, ob der Subprozess auf Eingabe wartet oder Ihnen eine Ausgabe gesendet hat, außer durch Schreiben und Lesen von den Pipes. Sie müssen also möglicherweise einen zweiten Thread starten, so dass Sie auf die Ausgabe proc.stdout warten und gleichzeitig auf proc.stdin schreiben können, ohne in einen Deadlock zu geraten, da beide Prozesse auf Pipe-E/A blockieren (oder wenn Sie auf einem Unix sind unterstützt die Auswahl mit Dateihandles, verwenden Sie select, um zu bestimmen, welche Pipes bereit sind zu empfangen oder bereit zum Lesen von).

0

Das klingt wie ein Job für eine Ereignisschleife. Das subprocess Modul zeigt seine Belastung bei komplexen Aufgaben.

Ich habe dies mit Twisted-getan, von Subklassen folgenden:

twisted.internet.endpoints.ProcessEndpoint 
twisted.protocols.basic.LineOnlyReceiver 

meisten Dokumentation für Twisted verwendet Sockets als Endpunkte, aber es ist nicht schwer, den Code für die Prozesse anzupassen.