子进程 popen:为什么所有写入都在子进程中同时发生?

Subprocess popen: Why do all writes happen at once in child process?

我有两个脚本,一个控制另一个并通过标准输入与之通信。父脚本:

import subprocess
import time

p = subprocess.Popen(['python','read_from_stdin.py'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)

for i in range(0,10):
    p.stdin.write(str(i))
    p.stdin.write('\r\n') # \n is not sufficient on Windows
    p.stdin.flush()
    print i
    time.sleep(1)

p.stdin.close()

子脚本(称为'read_from_stdin.py'):

import sys
import datetime

with open(datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt','w') as f:

    for line in sys.stdin:
        f.write(datetime.datetime.now().isoformat() + ' ' + line)

在子脚本创建的文件中,所有输入都具有相同的时间戳,尽管被父脚本分开写入一秒钟,尽管使用了 flush()。

编辑:根据下面 Karoly Horvath 的评论,它不是等待 EOF 的情况,而是存在缓冲。下面的不同子脚本确实按预期工作。

我发现了关于这个主题的问题:How do you read from stdin in Python?

一个公平的答案是:

The answer proposed by others:

for line in sys.stdin:
  print line

is very simple and pythonic, but it must be noted that the script will wait until EOF before starting to iterate on the lines of input.

此子脚本的行为符合预期:

import sys
import datetime

with open(datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt','w') as f:

    line = sys.stdin.readline()
    while line:
        f.write(datetime.datetime.now().isoformat() + ' ' + line)
        line = sys.stdin.readline()

    f.write('Finished')

它是 the read-ahead bug in Python 2: for line in sys.stdin: 在其内部缓冲区已满之前不会产生任何东西。使用 for line in iter(sys.stdin.readline, ''): 来解决它。