Linux 如何从 subprocess.Popen() 获取输出。proc.stdout.readline() 块,没有数据打印出来
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1388753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get output from subprocess.Popen(). proc.stdout.readline() blocks, no data prints out
提问by wearetherock
I want output from execute Test_Pipe.py, I tried following code on Linux but it did not work.
我想要执行 Test_Pipe.py 的输出,我尝试在 Linux 上执行以下代码,但没有奏效。
Test_Pipe.py
Test_Pipe.py
import time
while True :
print "Someting ..."
time.sleep(.1)
Caller.py
调用者.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.
线路proc.stdout.readline()
被阻塞,所以没有数据打印出来。
回答by Nadia Alramli
You obviously can use subprocess.communicate but I think you are looking for real time input and output.
您显然可以使用 subprocess.communicate 但我认为您正在寻找实时输入和输出。
readline was blocked because the process is probably waiting on your input. You can read character by character to overcome this like the following:
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()
回答by Alex Martelli
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 pexpectfor all non-Windows platform, wexpecton Windows, instead of subprocess
, when such tasks are desired.
为了避免总是可以缓冲的任务,如“让子进程的输出实时主进程”出现的很多问题,我总是建议使用Pexpect的所有非Windows平台,wexpect在Windows,而不是subprocess
,例如当任务是需要的。
回答by Derrick Petzold
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
Nadia 的代码段确实有效,但强烈不推荐使用 1 字节缓冲区调用 read。更好的方法是使用 fcntl 将 stdout 文件描述符设置为非阻塞
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
然后使用select测试数据是否准备好
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.
她是正确的,因为您的问题必须与您发布的问题不同,因为 Caller.py 和 Test_Pipe.py 确实按提供的方式工作。
回答by jfs
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).
Test_Pipe.py
默认情况下缓冲其标准输出,因此proc
在Caller.py
子缓冲区已满之前看不到任何输出(如果缓冲区大小为 8KB,则填充Test_Pipe.py
标准输出缓冲区需要大约一分钟)。
To make the output unbuffered (line-buffered for text streams) you could pass -u
flagto the child Python script. It allows to read subprocess' output line by line in "real-time":
要使输出无缓冲(文本流的行缓冲),您可以将-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()
See links in Python: read streaming input from subprocess.communicate()on how to solve the block-buffering issue for non-Python child processes.
请参阅Python 中的链接:从 subprocess.communicate() 读取流输入,了解如何解决非 Python 子进程的块缓冲问题。