实时从Windows上的subprocess.stdout读取

要强调的是,问题是实时读取而不是非阻塞读取 。 之前有人问过,例如subprocess.Popen.stdout – 再次读取stdout 。 但是没有提出令人满意的解决scheme。

作为一个例子,下面的代码尝试模拟python shell。

import subprocess p = subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) while True: line = input('>>> ') p.stdin.write(line.encode()) print('>>> ', p.stdout.read().decode()) 

但是,从p.stdout读取时会被阻塞。 经过四处搜寻,我发现了以下两种可能的结果。

  1. 使用fctrlO_NONBLOCK
  2. 使用threadqueue

而第一个soution可能工作,只能在linux上工作,第二个soution只是把阻塞读取变成非阻塞读取,即我不能得到subprocess的实时输出。 例如,如果我input“ print("hello") ”, p.stdout使用p.stdout解决scheme时,我将不会从p.stdout获得任何信息。

也许,有人会build议p.communite 。 不幸的是,在这种情况下它不适合,因为它会closuresstdin,如下所述。

那么,有没有Windows的解决scheme?

编辑:即使-u打开, p.stdout.read被replace为p.stdout.readline ,问题仍然存在。

 import subprocess p = subprocess.Popen(['python', '-u'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) while True: line = input('>>> ') p.stdin.write(line.encode()) p.stdin.flush() print('>>> ', p.stdout.readline().decode()) 

解决scheme:以下是基于JF Sebastian的回答和评论的最终代码。

 from subprocess import Popen, PIPE, STDOUT with Popen( ['python', '-i', '-q'], stdin=PIPE, stdout=PIPE, stderr=STDOUT, bufsize=0 ) as process: while True: line = input('>>> ') if not line: break process.stdin.write((line+'\n').encode()) print(process.stdout.readline().decode(), end='') 

应该注意的是,当命令没有输出时,程序会挂起。

下面是一个完整的工作示例,它交互地使用子进程:

 #!/usr/bin/env python3 import sys from subprocess import Popen, PIPE, DEVNULL with Popen([sys.executable, '-i'], stdin=PIPE, stdout=PIPE, stderr=DEVNULL, universal_newlines=True) as process: for i in range(10): print("{}**2".format(i), file=process.stdin, flush=True) square = process.stdout.readline() print(square, end='') 

下面是另一个例子: 如何[sys.executable, '-u', 'test.py']地运行[sys.executable, '-u', 'test.py']