41

我想要执行 Test_Pipe.py 的输出,我在 Linux 上尝试了以下代码,但没有成功。

Test_Pipe.py

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

调用者.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

4 回答 4

47

您显然可以使用 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()
于 2009-09-07T11:04:18.863 回答
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 所提供的工作不同。

于 2010-08-21T07:03:19.627 回答
15

Test_Pipe.py默认情况下缓冲其标准输出,因此在子缓冲区已满之前procin看不到任何输出(如果缓冲区大小为 8KB,则填充标准输出缓冲区大约需要一分钟)。Caller.pyTest_Pipe.py

要使输出无缓冲(文本流的行缓冲),您可以将-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()

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

于 2013-07-17T13:53:02.633 回答
14

为了避免诸如“实时获取子进程的输出到主进程”之类的任务缓冲经常出现的许多问题,我总是建议对所有非 Windows 平台使用pexpect ,在 Windows 上使用wexpect,而不是subprocess, 当这样的时候任务是需要的。

于 2009-09-07T16:10:41.603 回答