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

发布于 2024-08-04 14:19:19 字数 517 浏览 6 评论 0原文

我想要执行 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() 行被阻塞,因此没有数据打印出来。

I want output from execute Test_Pipe.py, I tried following code on Linux but it did not work.

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)

The line proc.stdout.readline() was blocked, so no data prints out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小姐丶请自重 2024-08-11 14:19:19

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

You obviously can use subprocess.communicate but I think you are looking for real time input and output.

readline was blocked because the process is probably waiting on your input. You can read character by character to overcome this like the following:

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()
椵侞 2024-08-11 14:19:19

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 按规定工作。

Nadia's snippet does work but calling read with a 1 byte buffer is highly unrecommended. The better way to do this would be to set the stdout file descriptor to nonblocking using fcntl

fcntl.fcntl(
    proc.stdout.fileno(),
    fcntl.F_SETFL,
    fcntl.fcntl(proc.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK,
)

and then using select to test if the data is ready

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

She was correct in that your problem must be different from what you posted as Caller.py and Test_Pipe.py do work as provided.

野心澎湃 2024-08-11 14:19:19

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

要使输出无缓冲(文本流的行缓冲),您可以传递 < code>-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:从 subprocess.communicate 读取流输入( ),了解如何解决非 Python 子进程的块缓冲问题。

Test_Pipe.py buffers its stdout by default so proc in Caller.py doesn't see any output until the child's buffer is full (if the buffer size is 8KB then it takes around a minute to fill Test_Pipe.py's stdout buffer).

To make the output unbuffered (line-buffered for text streams) you could pass -u flag to the child Python script. It allows to read subprocess' output line by line in "real-time":

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()

See links in Python: read streaming input from subprocess.communicate() on how to solve the block-buffering issue for non-Python child processes.

御守 2024-08-11 14:19:19

为了避免缓冲任务(例如“实时获取子进程的输出到主进程”)时可能出现的许多问题,我始终建议使用 pexpect 适用于所有非 Windows 平台,wexpect,而不是 subprocess

To avoid the many problems that can always arise with buffering for tasks such as "getting the subprocess's output to the main process in real time", I always recommend using pexpect for all non-Windows platform, wexpect on Windows, instead of subprocess, when such tasks are desired.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文