Ho un programma che interagisce con l'utente (agisce come una shell), e voglio eseguirlo usando il modulo subprocess python in modo interattivo. Ciò significa che voglio la possibilità di scrivere su stdin e ottenere immediatamente l'output da stdout. Ho provato molte soluzioni offerte qui, ma nessuna sembra funzionare per i miei bisogni.Input/output interattivo usando python
Il codice che ho scritto sulla base di Running an interactive command from within 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)
Il problema è che la coda rimane vuoto, come se non v'è alcuna uscita. Solo se scrivo per stdin tutti gli input che il programma deve eseguire e terminare, ottengo l'output (che non è quello che voglio). Per esempio se faccio qualcosa del tipo:
p.stdin.write("1\n5\n")
errors = getOutput(errQueue)
output = getOutput(outQueue)
C'è un modo per fare ciò che voglio fare?
MODIFICA: Lo script verrà eseguito su una macchina Linux. Ho cambiato il mio script e cancellato universal_newlines = True + imposta bufsize su 1 e svuota lo stdin immediatamente dopo wrtie. Ancora non ottengo output.
secondo tentativo: ho provato questa soluzione e funziona per me:
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()
Non capisco esattamente cosa intendi. Quello che volevo fare all'inizio è leggere solo l'output parziale (una riga) –
Non ho capito il tuo esempio. Che cosa significa questa riga: p = Popen ([sys.executable, "-u", '-c' 'per la riga in iter (input, ""): print ("a" * int (riga) * 10 * * 6) '], stdin = PIPE, stdout = PIPE, bufsize = 1) significa? –
Hai ragione, ho modificato la mia seconda soluzione mentre la usavo. Il problema era che quando ho provato la soluzione all'inizio, l'ho provato sull'interprete python (non ho scritto lo script, l'ho testato solo manualmente), quindi ha funzionato (a causa del tempo di risposta lento umano). Quando ho provato a scrivere lo script, ho riscontrato il problema che hai menzionato, quindi ho aggiunto il ciclo while, finché l'input non è pronto. In realtà ottengo l'intero output o nulla (eccezione IOError), sarà utile se carico il codice sorgente a.out (è un programma C)? –