如何从subprocess.Popen()获取输出.proc.stdout.readline()块,没有数据打印出来

wea*_*ock 38 python linux subprocess popen

我想从执行Test_Pipe.py输出,我尝试在Linux上使用代码,但它没有用.

Test_Pipe.py

import time
while True :
    print "Someting ..."
    time.sleep(.1)
Run Code Online (Sandbox Code Playgroud)

Caller.py

import subprocess as subp
import time

proc = subp.Popen(["python", "Test_Pipe.py"], stdout=subp.PIPE, stdin=subp.PIPE)

while True :
    data = proc.stdout.readline() #block / wait
    print data
    time.sleep(.1)
Run Code Online (Sandbox Code Playgroud)

该行proc.stdout.readline()被阻止,因此没有数据打印出来.

Nad*_*mli 44

你显然可以使用subprocess.communicate,但我认为你正在寻找实时输入和输出.

readline被阻止,因为该进程可能正在等待您的输入.您可以按字符逐字阅读以解决此问题,如下所示:

import subprocess
import sys

process = subprocess.Popen(
    cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)

while True:
    out = process.stdout.read(1)
    if out == '' and process.poll() != None:
        break
    if out != '':
        sys.stdout.write(out)
        sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

  • [在这种情况下你不需要`process.poll()`(http://stackoverflow.com/a/17701672/4279). (3认同)

Der*_*old 21

Nadia的代码片段确实有效但是用1字节缓冲区调用read是非常不推荐的.更好的方法是使用fcntl将stdout文件描述符设置为非阻塞

fcntl.fcntl(
    proc.stdout.fileno(),
    fcntl.F_SETFL,
    fcntl.fcntl(proc.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK,
)
Run Code Online (Sandbox Code Playgroud)

然后使用select来测试数据是否准备就绪

while proc.poll() == None:
    readx = select.select([proc.stdout.fileno()], [], [])[0]
    if readx:
        chunk = proc.stdout.read()
        print chunk
Run Code Online (Sandbox Code Playgroud)

她是正确的,因为你的问题必须与你发布的Caller.py和Test_Pipe.py一样有效.


jfs*_*jfs 15

Test_Pipe.py默认情况下缓冲它的stdout,因此procCaller.py子缓冲区已满之前看不到任何输出(如果缓冲区大小为8KB,那么填充Test_Pipe.py的stdout缓冲区大约需要一分钟).

要使输出无缓冲(对文本流进行行缓冲),您可以将-u标志传递给子Python脚本.它允许"实时"逐行读取子进程的输出:

import sys
from subprocess import Popen, PIPE

proc = Popen([sys.executable, "-u", "Test_Pipe.py"], stdout=PIPE, bufsize=1)
for line in iter(proc.stdout.readline, b''):
    print line,
proc.communicate()
Run Code Online (Sandbox Code Playgroud)

请参阅Python中的链接:从subprocess.communicate()读取流输入,了解如何解决非Python子进程的块缓冲问题.

  • @DerrickPetzold:错了.`bufsize = 1`表示"行缓冲".它使用与`bufsize = -1`相同的缓冲区大小.如果您实际运行代码,您可能已经发现两条注释都是错误的(比较时间性能并测量读取第一个字节之前的时间) (7认同)

Ale*_*lli 13

为了避免总是可以缓冲的任务,如"让子进程的输出实时主进程"出现的很多问题,我总是建议使用Pexpect的所有非Windows平台,wexpect在Windows,而不是subprocess,例如当任务是理想的.