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

时间:2009-09-07 10:50:53

标签: python linux subprocess popen

我想从执行Test_Pipe.py输出,我尝试在Linux上使用代码,但它不起作用。

Test_Pipe.py

import time
while True :
    print "Someting ..."
    time.sleep(.1)

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)

proc.stdout.readline()行已被屏蔽,因此无法打印出数据。

4 个答案:

答案 0 :(得分:43)

你显然可以使用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()

答案 1 :(得分: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,
)

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

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

她的问题是正确的,因为你的问题必须与你发布的问题不同,因为Caller.py和Test_Pipe.py按照提供的方式工作。

答案 2 :(得分:13)

为了避免缓慢执行诸如“将子进程的输出实时输出到主进程”等任务的许多问题,我总是建议对所有非Windows平台使用pexpect {{ 3}}在Windows上,而不是subprocess,当需要这样的任务时。

答案 3 :(得分:13)

Test_Pipe.py默认缓冲其stdout,因此proc中的Caller.py在子缓冲区已满之前看不到任何输出(如果缓冲区大小为8KB则需要大约一分钟填写Test_Pipe.py的stdout缓冲区。)

要使输出无缓冲(对文本流进行行缓冲),您可以将-u flag传递给子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()

请参阅Python: read streaming input from subprocess.communicate()中有关如何解决非Python子进程的块缓冲问题的链接。