uscita sottoprocesso bufferizzato (ultima riga mancante)
-
19-09-2019 - |
Domanda
Devo essere vista qualcosa di terribilmente ovvio. Ho bisogno di eseguire un programma C, il suo output in tempo reale e, infine, analizzare la sua ultima linea, che dovrebbe essere semplice come l'ultima riga stampata è sempre lo stesso.
process = subprocess.Popen(args, shell = True,
stdout = subprocess.PIPE, stderr = subprocess.PIPE)
# None indicates that the process hasn't terminated yet.
while process.poll() is None:
# Always save the last non-emtpy line that was output by the child
# process, as it will write an empty line when closing its stdout.
out = process.stdout.readline()
if out:
last_non_empty_line = out
if verbose:
sys.stdout.write(out)
sys.stdout.flush()
# Parse 'out' here...
Una volta ogni tanto, però, l'ultima riga non viene stampata. Il valore predefinito per delle Popens bufsize è 0, per cui si suppone che sia senza buffer. Ho anche provato, senza successo, l'aggiunta di fflush (stdout) per il codice C appena prima di uscire, ma sembra che non v'è assolutamente alcuna necessità di irrigare un flusso prima di uscire un programma.
idee chiunque?
Soluzione
readline()
ha per tamponare il testo, in attesa di una nuova linea.
Avrai sempre una condizione di competizione - nessuna quantità di flussi di un-buffered gestirà il fatto che si sta gestire una linea, quindi il controllo per l'uscita, poi la lettura di una linea, quindi se le uscite di processo parziali, mentre si sta la gestione di una linea, non leggerete niente altro. Inoltre, il guscio è probabilmente l'introduzione di un proprio buffer.
Quindi, si potrebbe o:
-
Usa
communicate()
e rinunciare alla output dettagliato mentre il sottoprocesso è in funzione. -
Assicurati di continuare a leggere dopo il processo è uscito, fino ad arrivare EOF.
Vorrei anche suggerire alterare il codice in modo che non c'è bisogno di usare shell=True
.
Altri suggerimenti
Il problema è che si sta leggendo le linee fino alle uscite di processo, (process.poll()
) mentre si utilizzati buffer a causa della bandiera shell.
Si dovrà continuare a leggere process.stdout fino a raggiungere la fine del file o la linea vuota.