Python - 如何在subprocess.Popen中从PIPE进行非阻塞读取?

时间:2015-04-07 11:00:49

标签: python pipe subprocess

我上周发布了类似的question,此帖反映了我的审判和我现在面临的问题。

通过Popen调用的程序是一个命令行程序。我使用一个线程从队列中读取一个项目并将其发送到stdin并从stdout获取响应。但是proc.stdout.read()挂起。我确实看到它在上周五的预期输出上正常工作,然后当我今天做了一些更改时,它就会挂起。我所做的更改是将read()替换为readlines()并使用循环来迭代结果。我知道readlines()可能会阻止,但是当我在上周五将代码转换到read()的位置时,它也会阻塞。我现在完全迷失了。任何可能的原因?

下面是从队列中获取一个句子并将其提供给java程序以获得响应的代码:

''' below is the code for worker thread. '''
def readQueue(proc, queue):
    print 'enter queueThread.\n'
    global notEmpty
    notEmpty = True
    while notEmpty:
        try:
            sen = queue.get()
            proc.stdin.write(sen.strip())
            res = proc.stdout.read()
            print res.strip(), ' ', sen
            queue.task_done()
        except Empty:
            break
    print 'leave queueThread.'

下面的主要线程是从文件中读取每一行并将其放入队列中,以便工作线程逐项处理:

def testSubprocess():
    ee = open('sentences.txt', 'r')
    #ff = open('result.txt', 'w')   # print it to stdout first before really write to a file. 
    lines = ee.readlines()
    cmd = ['java', 
           '-cp', 'someUsefulTools.jar', 
           'className', 
           '-stdin',]   # take input from stdin
    proc = Popen(cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE, bufsize=-1, universal_newlines=True)
    q = Queue()
    for sen in lines:
        q.put(sen.strip())
    readThread = Thread(target=readQueue, args=(proc, q))
    readThread.daemon = True
    readThread.start()
    print 'Main thread is waiting...\n'
    q.join()
    global notEmpty; notEmpty = False
    print 'Done!'

1 个答案:

答案 0 :(得分:1)

子流程中的管道就像文件一样。

如果您未指定应阅读的内容,这些对象上的方法read()会将所有内容读入内存,直到达到EOF为止,请参阅doc:https://docs.python.org/2/library/stdtypes.html#file.read

如果您不想要此行为,则必须设置要阅读的尺寸。尝试将其设置为1个字节?

readlines()也是如此,请参阅文档:https://docs.python.org/2/library/stdtypes.html#file.readlines