python 3.4 子流程

python 3.4 sub process

我正在尝试控制子进程并控制此进程的标准输出和标准输入。 它在 python 2.7 上运行良好,但在使用 python 3 时它无法 运行.

我在python2.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)

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

  • bufsize=0(无缓冲)默认为 Python 2.7
  • bufsize=-1(完全缓冲)在 Python 3.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='')

这是一个完整的代码示例。

注意:一般来说,除非您确切知道您需要阅读多少内容(如示例中:一行输入 -> 一行输出); input/output 可能会变得不同步并且可能会发生死锁,例如,如果子进程产生的输出少于您的预期,那么您的进程将在 .readline() 上阻塞,而子进程同时挂起等待您的输入。更强大的解决方案将异步处理子进程的流(asyncio、线程、select)。