子进程标准输入在缓冲区大小为1时无法刷新换行符

8

我有两个小的Python文件,第一个使用 input 读取一行内容,然后打印出另一行。

a = input()
print('complete')

第二次尝试将其作为子进程运行。
import subprocess

proc = subprocess.Popen('./simp.py',
                        stdout=subprocess.PIPE,
                        stdin=subprocess.PIPE,
                        bufsize=1)
print('writing')
proc.stdin.write(b'hey\n')
print('reading')
proc.stdout.readline()

上述脚本将会输出 "writing" 和 "reading",但是会卡住。一开始我以为这是标准输出缓冲问题,因此我将 bufsize=1 改成了 bufsize=0,这确实解决了问题。然而,似乎是标准输入引起的问题。
bufsize=1 时,如果在写入后添加 proc.stdin.flush(),进程就会继续执行。这两种方法都很笨拙,因为 (1) 无缓冲流很慢 (2) 到处添加刷新容易出错。为什么上面的 write 没有在换行时刷新呢?文档中说,bufsize 用于创建子进程的标准输入、标准输出和标准错误流,那么是什么导致了写操作没有在换行时刷新呢?

确实好奇。在Python 2.x上,bufsize=1可以正常工作。 - tdelaney
这是Python 3中的一个错误。已经修复了文本模式下的问题。请参见子进程行缓冲仅在通用换行模式下工作。 - jfs
1个回答

7

来自文档"1表示行缓冲(仅在universal_newlines=True即文本模式下可用)"。这样可以正常工作:

import subprocess

proc = subprocess.Popen('./simp.py',
                        stdout=subprocess.PIPE,
                        stdin=subprocess.PIPE,
                        bufsize=1,
                        universal_newlines=True)

print('writing')
proc.stdin.write('hey\n')
print('reading')
proc.stdout.readline()

1
由于问题21396引入的修复程序,它在Python 3.4.1和Python 3.4.2(当前版本)中无法工作。 它已经在问题21332中得到修复(文档中的引用是由该修复引入的)。 - jfs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接