If this is my subprocess:
import time, sys for i in range(200): sys.stdout.write( 'reading %i\n'%i ) time.sleep(.02)
And this is the script controlling and modifying the output of the subprocess:
import subprocess, time, sys print 'starting' proc = subprocess.Popen( 'c:/test_apps/testcr.py', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE ) print 'process created' while True: #next_line = proc.communicate()[0] next_line = proc.stdout.readline() if next_line == '' and proc.poll() != None: break sys.stdout.write(next_line) sys.stdout.flush() print 'done'
Why is readline
and communicate
waiting until the process is done running? Is there a simple way to pass (and modify) the subprocess' stdout real-time?
I'm on Windows XP.
To capture the output of the subprocess. run method, use an additional argument named “capture_output=True”. You can individually access stdout and stderr values by using “output. stdout” and “output.
stdout. flush() forces it to “flush” the buffer, meaning that it will write everything in the buffer to the terminal, even if normally it would wait before doing so.
There the connection is not closed. So you do not need to close most probably. unrelated: you could use stdin=open('test. sql', 'rb', 0) to redirect child's stdin from the file without loading the whole file into your Python process first.
stdout=PIPE means that subprocess' stdout is redirected to a pipe that you should read e.g., using process.communicate() to read all at once or using process.stdout object to read via a file/iterator interfaces.
As Charles already mentioned, the problem is buffering. I ran in to a similar problem when writing some modules for SNMPd, and solved it by replacing stdout with an auto-flushing version.
I used the following code, inspired by some posts on ActiveState:
class FlushFile(object): """Write-only flushing wrapper for file-type objects.""" def __init__(self, f): self.f = f def write(self, x): self.f.write(x) self.f.flush() # Replace stdout with an automatically flushing version sys.stdout = FlushFile(sys.__stdout__)
Process output is buffered. On more UNIXy operating systems (or Cygwin), the pexpect module is available, which recites all the necessary incantations to avoid buffering-related issues. However, these incantations require a working pty module, which is not available on native (non-cygwin) win32 Python builds.
In the example case where you control the subprocess, you can just have it call sys.stdout.flush()
where necessary -- but for arbitrary subprocesses, that option isn't available.
See also the question "Why not just use a pipe (popen())?" in the pexpect FAQ.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With