I am trying to make a simple python script that starts a subprocess and monitors its standard output. Here is a snippet from the code:
process = subprocess.Popen([path_to_exe, os.path.join(temp_dir,temp_file)], stdout=subprocess.PIPE)
while True:
output=process.stdout.readline()
print "test"
The problem is that the script hangs on output=process.stdout.readline()
and that the line print "test"
only executes after the subprocess is terminated.
Is there a way to read standard output and print it without having to wait for the subprocess to terminate?
The subprocess which I am starting is a Windows binary for which I do not have the source code.
I have found several similar questions, but the answers are only applicable on Linux or in case I have the source of the suprocess I am starting.
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: Either a file-like object representing the pipe to be connected to the subprocess's standard output stream using connect_read_pipe() , or the constant subprocess. PIPE (the default). By default a new pipe will be created and connected.
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.
The subprocess module defines one class, Popen and a few wrapper functions that use that class. The constructor for Popen takes arguments to set up the new process so the parent can communicate with it via pipes. It provides all of the functionality of the other modules and functions it replaces, and more.
Check select module
import subprocess
import select
import time
x=subprocess.Popen(['/bin/bash','-c',"while true; do sleep 5; echo yes; done"],stdout=subprocess.PIPE)
y=select.poll()
y.register(x.stdout,select.POLLIN)
while True:
if y.poll(1):
print x.stdout.readline()
else:
print "nothing here"
time.sleep(1)
Threaded Solution for non posix systems:
import subprocess
from threading import Thread
import time
linebuffer=[]
x=subprocess.Popen(['/bin/bash','-c',"while true; do sleep 5; echo yes; done"],stdout=subprocess.PIPE)
def reader(f,buffer):
while True:
line=f.readline()
if line:
buffer.append(line)
else:
break
t=Thread(target=reader,args=(x.stdout,linebuffer))
t.daemon=True
t.start()
while True:
if linebuffer:
print linebuffer.pop(0)
else:
print "nothing here"
time.sleep(1)
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