如何使用用户提示流式传输子进程?

时间:2015-02-16 05:53:05

标签: python subprocess

这是我的子进程调用:

def myrun(cmd):
  p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  stdout = []
    while True:
      line = p.stdout.readline()
      stdout.append(line)
      print line,
      if line == '' and p.poll() != None:
          break
  return ''.join(stdout)

当我正常运行'cmd'时,输出通常类似于:

一些文字......
更多文字......
你想继续[是/否]? :y
更多输出......

但如上所示,使用子进程运行相同的'cmd',我的输出如下:

你想继续[是/否]? :y
一些文字......
更多文字......
更多输出......

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

这基本上是因为你的cmd程序通常存在缓冲。你必须禁用在该程序中发生的默认缓冲,以达到你想要的目的。

如果它是一个python文件,你正在运行cmd,如下所示,你可以使用python命令添加"-u"参数来获得你想要的结果

cmd = ["python", "-u", "/link/to/python/file.py"]
myrun(cmd)

根据python的man doc,

-u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x

如果要在shell中运行任何文件,我会说stdbuf命令是你的安全赌注。将-o选项与命令一起设置为0(零),您就可以了。

cmd = ["sh", "\path\to\sh\file.sh"]
unbuffered_cmd = ["stdbuf", "-o0", "-e0"] + cmd
myrun(unbuffered_cmd)

请注意,stdbuf附带GNU coreutils。所以它可能不是平台无关的。

即使在stdbuf存在且"-u"为python设置的情况下处于更安全的一方,也要将Popen的bufsize参数设置为1

Popen(cmd, stdout=PIPE, stderr=STDOUT, bufsize=1)

如果stdbuf也没有帮助,我没有选择: - )