In the Python code you posted, you are not using the correct threads:
inputready, outputready, exceptready = select.select( [proc.stdout, proc.stderr], # read list [proc.stdout, proc.stderr], # write list [proc.stdout, proc.stderr], # error list. 0) # time out.
I have not tried to fix it, but I am sure that reading and writing to the same set of streams is incorrect.
There are several errors in your example. Firstly, the python executable that you run as a child process does not output. Secondly, there is a race condition, since you can call select() 5 times in a row before the child process will output, in which case you will kill the process before reading anything.
I fixed the three problems mentioned above (recording list, starting a process that produces an exit and race condition). Try this sample and see if it works for you:
#!/usr/bin/python import subprocess, os, select, time path = "/usr/bin/python" proc = subprocess.Popen([path, "foo.py"], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for i in xrange(0,5): time.sleep(1) inputready, outputready, exceptready = select.select( [proc.stdout, proc.stderr], [proc.stdin,], [proc.stdout, proc.stderr, proc.stdin], 0) if not inputready: print "No Data", print inputready, outputready, exceptready for s in inputready: print s.fileno(),s.readline() proc.terminate() print "After Terminating" for i in xrange(0,5): inputready, outputready, exceptready = select.select( [proc.stdout, proc.stderr], [proc.stdin,], [proc.stdout, proc.stderr, proc.stdin], 0) if not inputready: print "No Data", print inputready, outputready, exceptready for s in inputready: print s.fileno(),s.readline()
The foo.py file that I used contained the following:
#!/usr/bin/python print "Hello, world!"
The next version (mostly remote redundant output to simplify reading the results):
#!/usr/bin/python import subprocess, os, select, time path = "/usr/bin/python" proc = subprocess.Popen([path, "foo.py"], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for i in xrange(0,5): time.sleep(1) inputready, outputready, exceptready = select.select( [proc.stdout, proc.stderr], [proc.stdin,], [proc.stdout, proc.stderr, proc.stdin], 0) for s in inputready: line = s.readline() if line: print s.fileno(), line proc.terminate() print "After Terminating" for i in xrange(0,5): time.sleep(1) inputready, outputready, exceptready = select.select( [proc.stdout, proc.stderr], [proc.stdin,], [proc.stdout, proc.stderr, proc.stdin], 0) for s in inputready: line = s.readline() if line: print s.fileno(), line
Gives the following output:
5 Hello world!
After finishing
Note that for some reason, using the timeout parameter in select.select() did not produce the expected results on my system, and I resorted to using time.sleep() .
Just FYI, running python like
/usr/bin/python 2>&1|tee test.out
seems to be working fine.
You cannot get this effect because this example still gives the python interpreter control tty. Without a tty control, the python interpreter does not print the Python version and does not display the >>> prompt.
A close example might be the following. You can replace /dev/null with a file containing commands to send to the interpreter.
/usr/bin/python </dev/null 2>&1|tee test.out
If you redirect nothing but the control tty (keyboard) as standard input to the process, you will not get the output from the python interpreter. This is why your code is not working.