I'm using the subprocess module to start a subprocess and connect to it's output stream (stdout). I want to be able to execute non-blocking reads on its stdout. Is there a way to make .readline non-blocking or to check if there is data on the stream before I invoke .readline
? I'd like this to be portable or at least work under Windows and Linux.
here is how I do it for now (It's blocking on the .readline
if no data is avaible):
p = subprocess.Popen('myprogram.exe', stdout = subprocess.PIPE)
output_str = p.stdout.readline()
EDIT: This implementation still blocks. Use J.F.Sebastian's answer instead.
I tried the top answer, but the additional risk and maintenance of thread code was worrisome.Looking through the io module (and being limited to 2.6), I found BufferedReader. This is my threadless, non-blocking solution.
Use select & read(1).
For readline()-like:
Here is my code, used to catch every output from subprocess ASAP, including partial lines. It pumps at same time and stdout and stderr in almost correct order.
Tested and correctly worked on Python 2.7 linux & windows.
Adding this answer here since it provides ability to set non-blocking pipes on Windows and Unix.
All the
ctypes
details are thanks to @techtonik's answer.There is a slightly modified version to be used both on Unix and Windows systems.
This way you can use the same function and exception for Unix and Windows code.
To avoid reading incomplete data, I ended up writing my own readline generator (which returns the byte string for each line).
Its a generator so you can for example...
One solution is to make another process to perform your read of the process, or make a thread of the process with a timeout.
Here's the threaded version of a timeout function:
http://code.activestate.com/recipes/473878/
However, do you need to read the stdout as it's coming in? Another solution may be to dump the output to a file and wait for the process to finish using p.wait().
This version of non-blocking read doesn't require special modules and will work out-of-the-box on majority of Linux distros.