python中subprocess.PIPE上的非阻塞读取

时间:2016-02-15 19:49:16

标签: python subprocess nonblocking

我在Non-blocking read on a subprocess.PIPE in python上阅读了问题/答案/评论,但我觉得有点缺乏。

当我实现所提供的解决方案时,我注意到当子流程自行结束时,这种方法最有效。但是,如果子流程提供了一个信息流,并且我们正在寻找单个输出匹配,那么这种方法不适用于我的需求(特别是对于Windows,如果这很重要)。

这是我的样本: ping.py

import time

def main():
    for x in range(100):
        print x
        time.sleep(1)

if __name__ == '__main__':
    print("Starting")
    time.sleep(2)
    main()

runner.py

import subprocess
import time
import sys
from Queue import Queue, Empty
from threading  import Thread

def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line)
    out.close()

#Start process we want to listen to
pPing = subprocess.Popen('ping.py', 
    shell=True,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    )

q = Queue()
t = Thread(target=enqueue_output, args=(pPing.stdout, q))
t.daemon = True
t.start()

#make sure it's started  
print ("get the first line")
try:
    line = q.get()
except Empty:
    pass
else:
    print line.strip()

#look for the 'magic' output
print("empty the queue")
while not q.empty():
    line = q.get_nowait().strip()
    if (line == "3"):
        print("got it!")
        sys.exit()
    else:
        print("not yet")

我的期望是跑步者将确保过程开始,然后等待魔法输出然后停止,这样做。但是,子流程运行的时间越长,流道运行的时间越长。但是由于'魔术'输出相对较快,我必须等到子进程结束才能得到任何处理。

我错过了什么?

谢谢, 罗伯特

1 个答案:

答案 0 :(得分:0)

好的,如果我理解你正在尝试做什么,问题在于ping仍然是跑步者的子进程。虽然您可以使读取调用无阻塞,但父进程在子进程仍在运行时实际上不会退出。如果您希望跑步者不要等待孩子完成,请阅读第一行和第一个魔术输出然后退出,您需要ping以取消与父进程的关联。请查看此代码示例以了解如何完成http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/。当然,您可以跳过它们关闭的部分并重新打开所有I / O流。

在同一个注释中,我不确定是否将连接到父级的开放I / O流允许父级退出,因此如果这恰好是一个问题,您可能需要找出另一种交换数据的方法。