Interaktive Eingabe - /Ausgabe mit python
Ich habe ein Programm, mit dem Benutzer interagiert (verhält sich wie eine shell), und ich will das es läuft mit python-subprocess-Modul interaktiv.
Das bedeutet, dass ich die Möglichkeit zum schreiben auf stdin und sofort bekommen Sie die Ausgabe von stdout. Ich habe versucht, viele Lösungen, die hier angeboten werden, aber keiner von Ihnen scheint zu funktionieren für meine Bedürfnisse.
Den code, den ich geschrieben habe, basiert auf Ausführen einer interaktiven Befehl in python
import Queue
import threading
import subprocess
def enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
def getOutput(outQueue):
outStr = ''
try:
while True: #Adds output from the Queue until it is empty
outStr+=outQueue.get_nowait()
except Queue.Empty:
return outStr
p = subprocess.Popen("./a.out", stdin=subprocess.PIPE, stout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize = 1)
#p = subprocess.Popen("./a.out", stdin=subprocess.PIPE, stout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, universal_newlines=True)
outQueue = Queue()
errQueue = Queue()
outThread = Thread(target=enqueue_output, args=(p.stdout, outQueue))
errThread = Thread(target=enqueue_output, args=(p.stderr, errQueue))
outThread.daemon = True
errThread.daemon = True
outThread.start()
errThread.start()
p.stdin.write("1\n")
p.stdin.flush()
errors = getOutput(errQueue)
output = getOutput(outQueue)
p.stdin.write("5\n")
p.stdin.flush()
erros = getOutput(errQueue)
output = getOutput(outQueue)
Das problem ist, dass die Warteschlange bleibt leer, als wenn es gibt keine Ausgabe.
Nur wenn ich die schreiben von stdin, alle Eingaben, die das Programm benötigt zum ausführen und beenden, dann bekomme ich die Ausgabe (das ist nicht das, was ich will). Zum Beispiel, wenn ich etwas tun wie:
p.stdin.write("1\n5\n")
errors = getOutput(errQueue)
output = getOutput(outQueue)
Gibt es eine Möglichkeit, das zu tun, was ich tun will?
EDIT:
Das script läuft auf einem Linux-Rechner.
Ich änderte mein script gelöscht und die universal_newlines=True + gesetzt, die bufsize, 1 und gespült stdin sofort nach wrtie. Trotzdem bekomme ich keine Ausgabe.
Zweiten Versuch:
Ich habe versucht, diese Lösung und es funktioniert für mich:
from subprocess import Popen, PIPE
fw = open("tmpout", "wb")
fr = open("tmpout", "r")
p = Popen("./a.out", stdin = PIPE, stdout = fw, stderr = fw, bufsize = 1)
p.stdin.write("1\n")
out = fr.read()
p.stdin.write("5\n")
out = fr.read()
fw.close()
fr.close()
InformationsquelleAutor Talor Abramovich | 2013-11-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zwei Lösungen für dieses Problem unter Linux:
Erste ist die Verwendung eine Datei schreiben die Ausgabe an und Lesen Sie gleichzeitig:
Zweiten, als J. F. Sebastian angeboten, ist p.stdout und p.stderr Rohre non-blocking mit fnctl Modul:
Ich habe nicht verstanden, dein Beispiel. Was bedeutet diese Zeile: p = Popen([sys.ausführbare, "-u", '-c' für line in iter(input, ""): print("a"*int(line)*10**6)'], stdin=PIPE, stdout=PIPE, bufsize=1)?
Du hast Recht, habe ich bearbeitet meine zweite Lösung, wie ich es benutzt habe. Das problem war, dass als ich versuchte, die Lösung auf den ersten, habe ich versucht es auf der python-interpreter (ich habe nicht geschrieben, das Skript, nur getestet, es manuell ein), damit es funktioniert (die durch menschliche langsame Reaktionszeit). Wenn ich habe versucht, das Skript zu schreiben, ich habe festgestellt das problem, das Sie erwähnt haben, so habe ich die while-Schleife, bis die Eingabe fertig ist. Ich tatsächlich die gesamte Ausgabe oder gar nichts (IOError-Ausnahme), wird es hilfreich sein, wenn ich lade die ein.source-code (es ist ein C-Programm)?
Leider ist das script ich möchte kommunizieren mit verwendet
stty -echo
wodurch es zu beschweren'standard input': Inappropriate ioctl for device
wenn Sie versuchen, verwenden Sie die erste Methode. (Die zweite Methode scheint nie zu Lesen, die korrekt ausgegeben.. vorausgesetzt, das Skript ist die Ausgabe)Die zweite Lösung hängt immer beim aufrufen einer einfachen C-Programms, das die 2 Eingaben mit scanf("%s", buf)
InformationsquelleAutor Talor Abramovich
Keiner der aktuellen Antworten, die für mich gearbeitet. Am Ende habe ich dieses arbeiten:
Getestet mit diesem
dummy.py
Skript:Die Vorbehalte sind: input/output Linien immer mit newline -, Spül-Kind stdin nach jedem schreiben, und verwenden Sie
readline()
vom Kind stdout (alle, dass es geschafft, in den Funktionen).Ist es eine ziemlich einfache Lösung, meiner Meinung nach (nicht von mir, ich habe es hier gefunden: https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/). Ich war mit Python 3.6.
InformationsquelleAutor gorcajo
Hier ist eine interaktive shell. Sie haben zum ausführen von read() in einem separaten thread, sonst wird es blockieren der write () -
InformationsquelleAutor Shawn