Python 从子进程标准输出可靠的非阻塞读取
注意:我有一个进程,它将一行写入标准输出(“打印”(“hello”)并等待原始输入。我使用p=subprocess.Popen运行这个进程,然后调用p.stdout.readline()…这将无限期阻塞。我正在设置shell=False…为什么我不能读取第一个输出Python 从子进程标准输出可靠的非阻塞读取,python,subprocess,stdout,nonblocking,Python,Subprocess,Stdout,Nonblocking,注意:我有一个进程,它将一行写入标准输出(“打印”(“hello”)并等待原始输入。我使用p=subprocess.Popen运行这个进程,然后调用p.stdout.readline()…这将无限期阻塞。我正在设置shell=False…为什么我不能读取第一个输出 p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin = subprocess.PIPE) p
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin = subprocess.PIPE)
print(p.stdout.readline())
我看到过关于子进程非阻塞io的线程。我正在尝试创建一个交互式子进程对象来读取和写入进程。我发现即使有输出发送到stdout,stdout也在阻塞。为了测试这一点,我编写了一个程序,向stdout吐出递增的整数,并通过subprocess调用它。然后我告诉我们我发现,尽管进程每秒向标准输出1000行,但标准输出一次阻塞很长时间,完全随机返回一行……千分之一,然后十分之一,等等。有没有想过为什么会发生这种情况?如果我放慢速度打印机每0.5秒打印一次,我从未从stdout中读取数据。它需要1000次写入sdtout,然后才能用一行响应
注:
我设置了一个睡眠,这样在启动侦听线程和读取线程之间就有了一段时间。现在,我总是从stdout返回,但我随机得到一行。我想我不理解stdout。它不是缓冲区吗?我的意思是,我想得到进程中吐出的所有内容,但它似乎只保存了最后一行。我找不到documen这些管道上的东西
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
编辑:
哇,对不起,我完全错过了你在另一个过程中试图读取输入的部分
那么,fn您的另一个过程,看起来像:
print('Hello')
in = raw_input()
然后,打印实际上会将内容发送到前面传递的类似对象PIPE
的文件中,该文件具有自己的缓冲机制
要解决此问题,只需在打印
和原始输入
之间添加一个sys.stdout.flush()
:
print('Hello')
sys.stdout.flush() # "flush" the output to our PIPE
in = raw_input()
可能重复的我已经开始尝试winpexpect,但令人惊讶的是,这也会阻止!如果您的所有过程都是打印一行,然后等待输入,winpexpect会阻止,然后引发异常!!!readline()会阻止,因此取决于应用程序。将该行与空行(“”)进行比较这意味着while循环将继续运行(永不结束)。我同意,条件是完全任意的,当应用程序需要时,您有责任打破读取循环