2012-04-28 16 views
7

Sto provando a parlare con un processo figlio utilizzando la chiamata subprocess.Popen() python. Nel mio codice reale, sto implementando un tipo di IPC, quindi desidero scrivere alcuni dati, leggere la risposta, scrivere altri dati, leggere la risposta e così via. Per questo motivo, non posso usare Popen.communicate(), che altrimenti funziona bene per il caso semplice.Lettura/scrittura di un sottoprocesso Popen()

Questo codice mostra il mio problema. Non ottiene mai la prima risposta, si blocca al primo "Risultato di lettura". Perché? Come posso fare questo lavoro come mi aspetto?

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
print "Reading result:" 
print p.stdout.readline() 

p.stdin.write("cat\n") 
print "Reading result:" 
print p.stdout.readline() 

risposta

4

Proverei ad usare Popen().communicate() se è possibile perché fa un sacco di cose carine per te, ma se hai bisogno di usare Popen() esattamente come hai descritto, dovrai impostare sed per svuotare il suo buffer dopo newlines con l'opzione -l:

p = subprocess.Popen(['sed', '-l', 's/a/x/g'], 
        stdout=subprocess.PIPE, 
        stdin=subprocess.PIPE) 

e il codice dovrebbe funzionare bene

+1

Effettivamente funziona! Il mio sed per qualche motivo usa -u per "unbuffered", non -l, ma funziona lo stesso. Questo risolve il mio codice di esempio, ma sfortunatamente non è il mio vero codice, poiché il comando attuale non è sed, ma un altro programma python. Buona risposta, hai individuato il problema. –

+1

Sì, problema risolto. Il problema è stato il buffering dell'output del risultato. Fare un semplice stdout.flush() nel mio sottoprocesso ha risolto il problema. Grazie! –

3

s' sed uscita bufferizzata ed emette solo i dati fino abbastanza è stato accumulato, oppure il flusso di input è esaurita e chiusa.

Prova questo:

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
p.stdin.write("cat\n") 
p.stdin.close() 

print "Reading result 1:" 
print p.stdout.readline() 

print "Reading result 2:" 
print p.stdout.readline() 

essere consapevoli che questo non può essere fatto in modo affidabile che enormi dati come Wriring a stdin blocchi una volta che il buffer è pieno. Il modo migliore per farlo è usare communicate().

+0

Ma sed non agisce in questo modo quando si esegue il comando nella shell direttamente. Se lo fai, la risposta arriva dopo ogni riga. E il problema rimane anche se chiamo p.stdin.flush() dopo aver scritto. Inoltre, nella vita reale, ho scritto anche il programma chiamato, non c'è buffer e si comporta allo stesso modo. Non sono convinto che il buffering sia il problema qui. –

+2

Ah, avevi ragione, il buffering era davvero il problema. –

Problemi correlati