Reputation: 7526
So, I have been facing a problem with using subprocess for a python app i am writing. To illustrate the problem, I wrote this small script that replicates my problem pretty well.
from __future__ import print_function
import subprocess as sp
from select import select
p = sp.Popen(['ls'], stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
p.stdin.close()
while p.returncode is None or p.stdout.closed or p.stderr.closed:
# print('returncode is', p.returncode)
available_readers = select([p.stdout, p.stderr], [], [], 2.0)[0]
for r in available_readers:
print(r.read(1))
# output_display.insert(tk.END, r.read(1))
Ofcourse, we all know that ls
command exists immediately after printing some stuff to stdout
(or may be stderr
), but the above script never exists.
As you can see from the last line (comment) in the above script, I have to put the content from the subprocess into a tk text component. So, I can't use methods like .communicate
and other blocking calls as the command I need to run takes a long time and I need to show the output (almost) realtime. (Ofcourse, I have to run this in a separate thread when running Tk, but that's something else).
So, I am unable to understand why this script never exits. It keeps printing empty strings forever (after the expected output of the ls
command).
Please advise. I am running python 2.6.6 on ubuntu 10.10
Edit: Here's the version of the above script that works
from __future__ import print_function
import subprocess as sp
from select import select
p = sp.Popen(['ls'], stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
p.stdin.close()
while p.poll() is None:
# print('returncode is', p.returncode)
available_readers = select([p.stdout, p.stderr], [], [], 2.0)[0]
for r in available_readers:
print(r.read(1), end='')
# output_display.insert(tk.END, r.read(1))
print(p.stdout.read(), end='')
print(p.stderr.read(), end='')
Upvotes: 0
Views: 1481
Reputation: 287835
while p.returncode is None or p.stdout.closed or p.stderr.closed:
loops while any of the conditions is true. You probably meant to check just returncode
(and poll
in every iteration).
Upvotes: 1