Umgehen Pufferung der Subprozess Ausgang mit popen in C oder Python
Frage
ich eine allgemeine Frage zu popen (und alle damit verbundenen Funktionen), die für alle Betriebssysteme, wenn ich einen Python-Skript oder einen C-Code und führen Sie die ausführbare Datei aus der Konsole (gewinnen oder Linux) schreibe, kann ich sofort siehe die Ausgabe von dem Prozess. Allerdings, wenn ich laufe die gleiche ausführbare Datei als ein gegabelter Prozess mit seinem stdout in ein Rohr umgeleitet, irgendwo die Ausgangspuffer, in der Regel auf 4096 Bytes, bevor es auf das Rohr geschrieben wird, in dem der übergeordneten Prozess gelesen werden kann.
Der folgende Python-Skript ausgegeben in Blöcken von 1024 Bytes erzeugen
import os, sys, time
if __name__ == "__main__":
dye = '@'*1024
for i in range (0,8):
print dye
time.sleep(1)
Der folgende Python-Skript, das vorherige Skript ausführen und die Ausgabe so schnell lesen, wie es auf das Rohr, Byte für Byte kommt
import os, sys, subprocess, time, thread
if __name__ == "__main__":
execArgs = ["c:\\python25\\python.exe", "C:\\Scripts\\PythonScratch\\byte_stream.py"]
p = subprocess.Popen(execArgs, bufsize=0, stdout=subprocess.PIPE)
while p.returncode == None:
data = p.stdout.read(1)
sys.stdout.write(data)
p.poll()
Stellen Sie den Pfad für Ihr Betriebssystem. Wenn in dieser Konfiguration ausführen, wird die Ausgabe erscheint nicht in Blöcken von 1024 aber Stücken von 4096, trotz der Puffergröße des popen Befehls auf 0 gesetzt wird (die Standardeinstellung ist sowieso). Kann mir jemand sagen, wie dieses Verhalten ändern ?, ist es eine Möglichkeit, das Betriebssystem zwingen kann, den Ausgang von dem gegabelten Prozess in der gleichen Art und Weise, wie zu behandeln, wenn sie von der Konsole ausgeführt wird ?, dh nur die Daten durchschlagen ohne Pufferung?
Lösung
Im Allgemeinen ist die Standard-C-Laufzeitbibliothek (das ist auf jedem System im Namen von fast jedem Programm ausgeführt wird, mehr oder weniger ;-) erkennt, ob stdout ein Terminal ist oder nicht; wenn nicht, es puffert die Ausgabe (das ist eine große Effizienz zu gewinnen, im Vergleich zu ungepufferten ausgegeben werden kann).
Wenn Sie die Kontrolle über das Programm sind, die das Schreiben tut, können Sie (als eine andere Antwort vorgeschlagen) bündig stdout kontinuierlich, oder (elegant, wenn möglich) versuchen stdout zu zwingen ungepufferte zu sein, z.B. von Python mit dem -u
Kommandozeilen-Flag ausgeführt werden:
-u : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)
see man page for details on internal buffering relating to '-u'
(was der Mann Seite hinzufügt, ist eine Erwähnung von stdin und Problemen mit Binär-Modus [s]).
Wenn Sie nicht oder wollen nicht, das Programm berühren, die, -u
oder dergleichen auf dem Programm schreiben, das gerade liest unwahrscheinlich ist, zu helfen (die Pufferung, dass die meisten zählt, ist der auf dem Schreib stdout geschieht, nicht das auf den Leser stdin). Die Alternative ist, den Schriftsteller dazu zu verleiten, zu glauben, dass es zu einem Terminal schreibt (obwohl in der Tat zu einem anderen Programm sie schreibt!), Über das pty
Standardbibliotheksmodul oder übergeordneten Dritten pexpect Modul (oder, für Windows, das Port wexpect ).
Andere Tipps
Das ist richtig, und gilt sowohl für Windows und Linux (und möglicherweise andere Systeme), mit popen()
und fopen()
. Wenn Sie die Ausgabepuffer vor 4096 Bytes geschickt werden sollen, verwenden fflush()
(auf C) oder sys.stdout.flush()
(Python).