python 3.4子进程

python 3.4子进程,python,python-2.7,subprocess,python-3.4,Python,Python 2.7,Subprocess,Python 3.4,我试图控制子进程并控制此进程的标准输出和标准输入。 它在Python2.7中工作得很好,但在使用Python3时它无法运行 我用python 2.7编写了以下代码: print("python 2.7:\n") proc = subprocess.Popen(['cat -'], shell = True, stdin = subprocess.PIPE,

我试图控制子进程并控制此进程的标准输出和标准输入。 它在Python2.7中工作得很好,但在使用Python3时它无法运行

我用python 2.7编写了以下代码:

print("python 2.7:\n")
proc = subprocess.Popen(['cat -'],
                        shell = True,
                        stdin = subprocess.PIPE, 
                        stdout = subprocess.PIPE,
                        #stderr = subprocess.PIPE,
                        )
for i in range(10):
    proc.stdin.write('%d\n' % i)
    output = proc.stdout.readline()
    print (output.rstrip())

remainder = proc.communicate()[0]
remainder = remainder.replace("(","").replace(")","").replace("'","").split(",")[0]
print("-----------------")
print(remainder)
正如我所说的,这段代码工作得很好,但是当试图用python 3.4编写它时,我没有正确地使用stdin.write

print("python 3.4:\n")
proc = subprocess.Popen(['cat -'],
                        shell = True,
                        stdin = subprocess.PIPE, 
                        stdout = subprocess.PIPE,
                        stderr = subprocess.PIPE,
                        universal_newlines = True

                        )

for i in range(10):
    inp = str(i)
    proc.stdin.flush()
    proc.stdout.flush()
    proc.stdin.write(inp)

    output = proc.stdout.read()
    print (output.rstrip())

remainder = proc.communicate()[0]
remainder = remainder.replace("(","").replace(")","").replace("'","").split(",")[0]
print("-----------------")
print(remainder)

你快到了。这是一个缓冲问题:

默认情况下,Python 2.7上的bufsize=0无缓冲 bufsize=-1在Python3.4上完全缓冲默认值已更改 您应该将proc.stdin.flush放在proc.stdin.write之后.write调用之前,缓冲区为空-没有要刷新的内容:

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

with Popen(['cat'], stdin=PIPE, stdout=PIPE, bufsize=1,
           universal_newlines=True) as process:
    for i in range(10):
        print(i, file=process.stdin, flush=True)
        output = process.stdout.readline()
        print(output, end='')
这是一个完整的代码示例


注意:一般来说,除非您确切地知道需要阅读多少,如示例中所示:一行输入->一行输出;输入/输出可能会变得不同步,并且可能发生死锁,例如,如果子进程产生的输出少于您预期的输出,则您的进程将在.readline上阻塞,而子进程同时挂起等待您的输入。一个更健壮的解决方案可以异步地处理子进程的流—异步IO、线程、选择。

除了下面的答案之外,output=proc.stdout.read将阻止读取文件,直到进程退出时出现EOF。循环的第二轮,如果你成功了,将不会成功。如果进程的stdin是管道而不是终端,那么它的行为可能会有所不同。unixy系统上的pexpect模块在这种情况下可以派上用场。@tdelaney:python 2.7代码可以工作,因此这里不需要使用pexpect。虽然总的来说。