注意:我有一个进程将一行写入标准输出 ("print("hello")) 并等待 raw_input。我使用 p = subprocess.Popen 运行这个进程,然后调用 p.stdout.readline()。 ...这会无限期地阻塞。我正在设置 shell=False...为什么我无法读取第一个输出?
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin = subprocess.PIPE)
print(p.stdout.readline())
我看过this关于子进程的非阻塞 io 的线程。我正在尝试创建一个交互式子进程对象来读取和写入进程。我发现 stdout 正在阻塞,即使有输出发送到 stdout。为了测试这一点,我编写了一个程序,将递增的整数输出到标准输出并通过子进程调用它。然后我使用涉及队列的非阻塞方法来读取标准输出。我发现,尽管该过程每秒向 stdout 吐出 1000 行,但 Stdout 一次阻塞很长时间,完全随机返回一行......千分之一,然后十分之一等。任何关于为什么会发生这种情况的想法?如果我将打印机放慢到每 0.5 秒打印一次,我就永远不会从 stdout 读取数据。就像它需要 1000 次写入 sdtout 才能用一行响应。
注意: 我睡了一会儿,所以在启动监听线程和从中读取之间有时间。现在,我总是从 stdout 返回,但我得到一个随机的单行。我想我不明白标准输出。不缓冲吗?我的意思是,我想得到我的过程吐出的所有内容,但它似乎只保存了最后一行。我找不到关于这些 PIPE 事物的文档。
def getStdOut(self):
'''
reads standard out
'''
return self.nonBlockingRead()
def enqueue_output(self, out, queue, kill):
line = ""
kill = True
while kill:
line = out.readline()
queue.put(line)
# for line in iter(out.readline, b''):
# queue.put(line)
# out.close()
def nonBlockingRead(self):
'''
taken from the internet
'''
import sys
from subprocess import PIPE, Popen
from threading import Thread
sleep(0.5) #I inserted this later
try:
from Queue import Queue, Empty
except ImportError:
from queue import Queue, Empty # python 3.x
ON_POSIX = 'posix' in sys.builtin_module_names
killThread = False
self.q = Queue()
t = Thread(target=self.enqueue_output, args=(self.theProcess.stdout, self.q, killThread))
t.daemon = True # thread dies with the program
t.start()
line = ''
try:
line = self.q.get_nowait() # or q.get(timeout=.1)
except Exception as e:
print(e)
print('no output yet')
killThread = True
return line
if __name__ == "__main__" :
'''
unit tests
'''
import time
cmd = 'python "C:\InteractiveTest.py"'
aSubProc = subProcessWStdIn(cmd, 10)
while True :
# print(aSubProc.writeToProcess('y'))
print(aSubProc.getStdOut())
最佳答案
readline
从类文件对象 PIPE
中读取一行,要读取所有内容,只需将其包装在一个 while 循环中即可。您还应该在每次读取后调用 sleep
以节省 CPU 周期。
这是一个简单的例子:
import subprocess
p = subprocess.Popen(
['ls', '-lat'],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE
)
while True:
line = p.stdout.readline()
if line == '':
break
print(line.strip()) # remove extra ws between lines
编辑:
哇哦,抱歉,我完全错过了您在其他进程中尝试读取输入的部分...
因此,在您的其他流程中,看起来像这样:
print('Hello')
in = raw_input()
然后 print 实际上将内容发送到您之前传递的类似文件的对象 PIPE
,它有自己的缓冲机制。 print()
function docs 中解释了此行为
要解决这个问题,只需在 print
和 raw_input
之间添加一个 sys.stdout.flush()
:
print('Hello')
sys.stdout.flush() # "flush" the output to our PIPE
in = raw_input()
关于python - 从子进程 stdout 可靠地非阻塞读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22044253/