Sto incontrando alcune difficoltà nell'ottenere l'output da una pipe di stdout del sottoprocesso. Sto lanciando qualche codice di terze parti tramite esso, al fine di estrarre l'output del registro. Fino a un recente aggiornamento del codice di terze parti, tutto ha funzionato bene. Dopo l'aggiornamento, python ha iniziato a bloccare a tempo indeterminato, senza mostrare alcun output. Posso avviare manualmente l'app di terze parti e vedere l'output.Output sottoprocesso Python su Windows?
Una versione di base del codice che sto utilizzando:
import subprocess, time
from threading import Thread
def enqueue_output(out):
print "Hello from enqueue_output"
for line in iter(out.readline,''):
line = line.rstrip("\r\n")
print "Got %s" % line
out.close()
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=1)
thread = Thread(target=enqueue_output, args=(proc.stdout,))
thread.daemon = True
thread.start()
time.sleep(30)
Questo funziona perfettamente se sostituisco third_party.exe in questo script:
import time, sys
while True:
print "Test"
sys.stdout.flush()
time.sleep(1)
Così io sono poco chiaro come alla magia deve essere fatto per farlo funzionare con il comando originale.
Queste sono tutte le varianti della linea subprocess.Popen che ho provato senza successo:
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=0)
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, shell=True)
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, creationflags=subprocess.CREATE_NEW_CONSOLE)
si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, startupinfo=si)
Edit 1: Non posso effettivamente utilizzare .communicate() in questo caso. L'app che sto lanciando rimane in esecuzione per lunghi periodi di tempo (da giorni a settimane). L'unico modo in cui avrei potuto testare .communicate() sarebbe stato quello di uccidere l'app poco dopo il suo avvio, che non credo mi avrebbe dato risultati validi.
Anche la versione non-threaded di questo fallisce:
import subprocess, time
from threading import Thread
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print "App started, reading output..."
for line in iter(proc.stdout.readline,''):
line = line.rstrip("\r\n")
print "Got: %s" % line
Edit 2: Grazie a JDI, le seguenti opere va bene:
import tempfile, time, subprocess
w = "test.txt"
f = open("test.txt","a")
p = subprocess.Popen("third_party.exe", shell=True, stdout=f,
stderr=subprocess.STDOUT, bufsize=0)
time.sleep(30)
with open("test.txt", 'r') as r:
for line in r:
print line
f.close()
È possibile che il programma di terze parti sia passato a scrivere su stderr? – jdi
Non sembra essere il caso. Se intercetto invece stderr, succede la stessa cosa (però, vedo l'output dell'app sulla console, ma è solo la stampa, non sta attraversando Python). – devicenull
Sembra che l'app abbia smesso di utilizzare l'output standard e stia scrivendo direttamente alla console. Se è così, non c'è molto che tu possa fare al riguardo. Sei in grado di verificare con il fornitore dell'app? –