实时读取stdout进程

BPL*_*BPL 17 python windows subprocess popen sublimetext3

让我们考虑一下这个片段:

from subprocess import Popen, PIPE, CalledProcessError


def execute(cmd):
    with Popen(cmd, shell=True, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
        for line in p.stdout:
            print(line, end='')

    if p.returncode != 0:
        raise CalledProcessError(p.returncode, p.args)

base_cmd = [
    "cmd", "/c", "d:\\virtual_envs\\py362_32\\Scripts\\activate",
    "&&"
]
cmd1 = " ".join(base_cmd + ['python -c "import sys; print(sys.version)"'])
cmd2 = " ".join(base_cmd + ["python -m http.server"])
Run Code Online (Sandbox Code Playgroud)

如果我运行execute(cmd1)输出将打印没有任何问题.

但是,如果我运行execute(cmd2)而不会打印任何内容,为什么会这样,我如何修复它,以便我可以实时看到http.server的输出.

另外,如何for line in p.stdout在内部进行评估?是什么样的无限循环,直到达到stoout eof或什么?

这个主题在SO中已经解决了几次,但我还没有找到一个Windows解决方案.上面的片段实际上是来自这个答案的代码并尝试从virtualenv运行http.server(在win7上运行python3.6.2-32bits)

Ole*_*nko 5

使用此代码,由于缓冲,您无法看到实时输出:

for line in p.stdout:
    print(line, end='')
Run Code Online (Sandbox Code Playgroud)

但如果你使用p.stdout.readline()它应该工作:

while True:
  line = p.stdout.readline()
  if not line: break
  print(line, end='')
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅相应的python bug讨论

UPD:在这里你可以找到 stackoverflow 上的各种解决方案几乎相同的问题.


fpb*_*bhb 5

如果要从正在运行的子进程中连续读取,则必须使进程的输出无缓冲.您的子进程是一个Python程序,这可以通过传递-u给解释器来完成:

python -u -m http.server

这就是它在Windows机器上的外观.

在此输入图像描述