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

How to stream subprocess output with a user prompt?

这是我的子流程调用:

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'时,输出通常是这样的:

一些文字...
更多文字...
你想继续[yes/no]吗? : y
更多输出...

但是运行使用上面显示的子进程使用相同的'cmd',我的输出是这样的:

你想继续[yes/no]吗? : y
一些文字...
更多文字...
更多输出...

我该如何解决这个问题?

这主要是因为 cmd 程序中通常存在的缓冲。您必须禁用该程序中发生的默认缓冲才能获得您要查找的内容。

如果它是一个 python 文件,你正在通过如下命令 运行ning,你可以在 python 命令中添加 "-u" 参数来获取你想要的结果

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

根据 python、

的 man 文档
-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 并且为 python 设置了 "-u",为了更安全,将 Popen 的 bufsize 参数设置为 1

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

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