所以,我一直面临着为我正在编写的python应用程序使用子进程的问题。为了说明这个问题,我编写了这个小脚本,可以很好地复制我的问题。
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))
当然,我们都知道在将某些内容打印到ls
(或者可能是stdout
)后立即存在stderr
命令,但上述脚本从不存在。
从上面脚本的最后一行(注释)可以看出,我必须将子进程中的内容放入tk文本组件中。所以,我不能使用像.communicate
这样的方法和其他阻塞调用,因为我需要运行的命令需要很长时间,我需要显示输出(几乎)实时。 (当然,我必须在运行Tk时在一个单独的线程中运行它,但这是其他的东西)。
所以,我无法理解为什么这个脚本永远不会退出。它会一直打印空字符串(在ls
命令的预期输出之后)。
请指教。我在ubuntu 10.10上运行python 2.6.6
编辑:以下是适用的上述脚本的版本
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='')
答案 0 :(得分:1)
while p.returncode is None or p.stdout.closed or p.stderr.closed:
当任何条件为真时,循环。您可能只想检查returncode
(以及每次迭代中的poll
)。