Python 从子进程标准输出可靠的非阻塞读取

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

注意:我有一个进程,它将一行写入标准输出(“打印”(“hello”)并等待原始输入。我使用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())
我看到过关于子进程非阻塞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循环将继续运行(永不结束)。我同意,条件是完全任意的,当应用程序需要时,您有责任打破读取循环