Come interagire correttamente con un processo usando il modulo sottoprocesso
-
22-07-2019 - |
Domanda
Sto riscontrando problemi nel reindirizzare lo stdio di un altro programma usando il modulo di sottoprocesso. Basta leggere da stdout per appendere e Popen.communicate () funziona ma chiude i tubi dopo aver letto / scritto. Qual è il modo più semplice per implementarlo?
Stavo giocando con questo su Windows:
import subprocess
proc = subprocess.Popen('python -c "while True: print \'Hi %s!\' % raw_input()"',
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
while True:
proc.stdin.write('world\n')
proc_read = proc.stdout.readline()
if proc_read:
print proc_read
Soluzione
Non si adatta al 100% al tuo esempio ma aiuta a comprendere il problema di fondo: il processo P avvia il figlio C. Il figlio C scrive qualcosa nel suo stdout. stdout di C è una pipe che ha un buffer di 4096 caratteri e l'output è più breve di quello. Ora, C attende alcuni input. Per C, va tutto bene.
P attende l'output che non arriverà mai perché il sistema operativo non vede alcun motivo per svuotare il buffer di output di C (con così pochi dati al suo interno). Poiché P non ottiene mai l'output di C, non scriverà mai nulla su C, quindi C si blocca in attesa dell'input da P.
Correzione: utilizzare flush dopo ogni scrittura su una pipe costringendo il sistema operativo a inviare i dati ora .
Nel tuo caso, aggiungendo proc.stdin.flush ()
nel ciclo while principale e un sys.stdout.flush ()
nel ciclo figlio dopo la stampa dovrebbe risolvere il tuo problema.
Dovresti anche considerare di spostare il codice che legge dall'altro processo in un thread. L'idea qui è che non puoi mai sapere quando arriveranno i dati e l'utilizzo di un thread ti aiuta a capire questi problemi mentre scrivi il codice che elabora i risultati.
In questo posto, volevo mostrarti la nuova documentazione di Python 2.6 ma non spiega nemmeno il problema del flush :( Oh beh ...