Python subprocess 永不退出且输出为空字符串

0 投票
1 回答
1465 浏览
提问于 2025-04-16 14:33

我在写一个Python应用的时候,遇到了使用子进程(subprocess)的问题。为了说明这个问题,我写了一个小脚本,能够很好地复现我的困扰。

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='')

1 个回答

1
while p.returncode is None or p.stdout.closed or p.stderr.closed:

循环会在任何条件为真时继续进行。你可能是想只检查一下returncode(并且在每次循环中检查poll)。

撰写回答