Pipe不会传递所有数据

时间:2017-03-02 05:19:13

标签: python

我试图复制subprocess.Popen(command, stdout=PIPE)对象的stdout上发生的事情,当生成的命令变得无响应并且read()调用开始阻塞时。这是所需的行为:创建管道,写入管道,从管道读取,一旦读取了所有数据,任何进一步的读取将被阻止。我已经在REPL确认了这个工作:

>>> import os
>>> os.pipe()
(3, 4)
>>> a = os.fdopen(3)
>>> b = os.fdopen(4, 'w')
>>> b.write("line 1\n"
...         "line 2\n"
...         "line 3\n"
...         "line 4\n"
...         "line 5\n")
>>> b.flush()
>>> a.readline()
'line 1\n'
>>> a.readline() 
'line 2\n'
>>> a.readline()
'line 3\n'
>>> a.readline()
'line 4\n'
>>> a.readline()
'line 5\n'
>>> a.readline()
    ## hangs here forever...

但是,在下面的代码中看似相同类型的事物只会在其余读取被阻止之前产生第一行输出。我做错了什么?

代码:

import os
import select


class Stuck():
    def __init__(self):
        pipe_readfd, pipe_writefd = os.pipe() 
        self.output = os.fdopen(pipe_readfd, 'r') 

        self.writer = os.fdopen(pipe_writefd, 'w')
        self.writer.write('output line 1\n'
                          'output line 2\n'
                          'output line 3\n'
                          'output line 4\n'
                          'output line 5\n')
        self.writer.flush()


class Runner():
    def run(self, timeout=3):
            stuck = Stuck()
            opendescriptors = [stuck.output]
            timeout_counter = 0 
            while opendescriptors:
                pending = select.select(opendescriptors, [], [], 1)[0]
                if not pending:
                    timeout_counter += 1
                    if timeout_counter >= timeout:
                        print "*** STUCK FOR OVER {} SECONDS ***\n".format(timeout)
                        return False
                else:
                    timeout_counter = 0 
                    for fd in pending:
                        line = fd.readline()
                        if line == '': 
                            opendescriptors.remove(fd)
                        else:
                            print line


def test():
    runner = Runner()
    runner.run() 
    print "Expecting five lines of output followed by TIMEOUT"


if __name__ == "__main__":
    test()

制作此内容:

output line 1

*** STUCK FOR OVER 3 SECONDS ***

Expecting five lines of output followed by TIMEOUT

1 个答案:

答案 0 :(得分:1)

据我所知,select()做了很多与readline()不搭配的东西。用os.read()替换select()会导致正确的行为。使用线程而不是interface ITest { void Create(int id); } 是另一种途径。