13

好的,所以我已经看到了十几个这样的线程,但是没有一个给出完整的答案,而且到目前为止我尝试的一切都对我不起作用。

1)不断输出一些数据并刷新它的脚本:

import time
import sys

if __name__ == '__main__':
    for i in range(5):
        print i,
        sys.stdout.flush()
        time.sleep(1)

2)使用 Popen 调用第一个脚本的脚本应该一个一个地打印数字,但由于某种原因没有,并且一次打印它们:

import sys
import subprocess

if __name__ == '__main__':
    process = subprocess.Popen(['python', 'flush.py'], stdout = subprocess.PIPE )
    for line in iter(process.stdout.readline, ''):
        print line,
        sys.stdout.flush()

我有点困惑的第一件事是在第一个脚本中,如果你删除刷新,它会在一行中返回输出 O_O ...我很确定这是因为 time.sleep 但仍然有点预期它会像一个标准输出不断返回值 0,1,2,3,4 但不是全部一起,当然 flush 解决了它,但很奇怪,至少对我来说......

主要问题: 第二个脚本是否没有一一返回数字,而是一次返回所有输出......我需要的是看到数字一一弹出......

我在某处读到它不会返回 Popen 等待关闭管道的 EOF,这就是它运行到最后的原因.....

那么接下来我该怎么做或尝试呢? 提前致谢。

4

1 回答 1

13

正如@Warren Weckesser 的评论所说,您的问题与缓冲问题无关。

.readline()父进程在读取换行符或到达 EOF 之前不会返回。您的子进程根本不打印任何换行符,因此您的父进程在子进程结束之前不会打印任何内容。

print i,最小的修复只是删除子脚本末尾的逗号。

这也有效:

#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE

p = Popen([sys.executable or 'python',
           '-u', # unbuffer stdout (or make it line-buffered on Python 3)
           '-c',
           """
import time

for i in range(5):
    print(i) # <-- no comma i.e., each number is on its own line
    time.sleep(1)
"""], stdout=PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
    print(int(line)**2)

例子:

 $ python parent.py
 0
 1
 4
 9
 16

这些数字每秒钟打印一次,无需等待子进程结束。

如果您不想更改子脚本,那么您应该使用readline()在空格处停止而不是换行符,例如:

#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE

p = Popen(['python2', 'child.py'], stdout=PIPE, bufsize=0)
for token in generate_tokens(p.stdout):
    print(int(token))

其中generate_tokens()产生空格分隔的标记:

def generate_tokens(pipe):
    buf = []
    while True:
        b = pipe.read(1) # read one byte
        if not b: # EOF
            pipe.close()
            if buf:
                yield b''.join(buf)
            return
        elif not b.isspace(): # grow token
            buf.append(b)
        elif buf: # full token read
            yield b''.join(buf)
            buf = []

它也会在孩子打印出整数后立即打印。

于 2013-12-13T21:16:49.587 回答