habe eine ganze Weile im Forum gestöbert, bin auch über eine Reihe von Threads gestolpert, wo mein Problem zumindest periphär behandelt wurde, ne Lösung hab ich aber nicht gefunden.
Daher brech ich das jetzt hier mal runter auf den Kern und bring ein Beispiel:
Ich starte aus Python heraus ein externes Programm. Ich benutze dazu popen2.Popen3, weil ich so a) an die PID komme, b) mein Python-Skript weiterläuft und ich nur gelegentlich mit poll() checken kann, ob das externe Programm fertig ist und ich c) saubere filedescriptors für stdout, stdin und stderr habe.
Funktioniert auch alles ganz hervorragend, solange nicht ein spezieller Fall eintritt. Wenn mein externes Programm mehr als 8192 Zeichen an stdout schreibt, dann ist der Puffer voll und das Programm wartet, bis irgendwer kommt und den Puffer leermacht. Ich sitzte aber auf der Parent-Seite und wundere mich, warum mir ein poll() erzählt, das Child würde nie fertig werden.
Jetzt könnte ich einfach mit fromchild.read() den Puffer leerlesen, read() wartet aber auch ein EOF, bevor es zurückkehrt, ich blockiere mir also den Parent. Ausserdem kann ich ja erstmal gar nicht sagen, ob das Child noch läuft oder wegen eines vollen Buffers schläft...
Zum Beispiel:
Erstmal eine mögliche Child-Applikation:
Code: Alles auswählen
import sys, time
output_size = 8191
for x in range(output_size):
sys.stdout.write("x")
time.sleep(5)
Code: Alles auswählen
import popen2, time
app = popen2.Popen3("child.py")
while app.poll() == -1:
time.sleep(1)
Nun könnte ich Parent erweitern:
Code: Alles auswählen
import popen2, time
app = popen2.Popen3("child.py")
stdout = ''
while app.poll() == -1:
stdout += app.fromchild.read()
time.sleep(1)
Im Übrigen scheint (zumindest unter HP-UX 11) die Angabe der bufsize (3. Parm beim Popen3) keinen Einfluss auf den tatsächlichen Puffer haben.
Gibt es irgendeine Möglichkeit, read() mitzugeben, dass es nur soviel lesen soll, wie gerade im Puffer ist? Kann man read() alternativ einen timeout mitgeben? Alternativ kann man Popen3 tatsächlich den Puffer vergrößern?
Ich bin bei meiner Recherche hier im Forum mehrmals über select.select() gestolpert. Leider bin ich nicht so tief in Python, als dass ich das Konzept verstanden hätte...
Am liebsten wär mir, wenn ich nicht gelegentlich noch den Puffer leeren müsste, sondern Popen3 einen entsprechend Großen zur Verfügung stellt.
Kann mir da jemand weiterhelfen?
Gruß
D