简体   繁体   English

在 Python 中对 subprocess.PIPE 进行非阻塞读取

[英]Non-blocking read on a subprocess.PIPE in Python

I read the question/answer/comments on A non-blocking read on a subprocess.PIPE in Python , but I felt a bit lacking.我阅读了A non-blocking read on a subprocess.PIPE in Python的问题/答案/评论,但我觉得有点缺乏。

When I implemented the solution provided, I noticed that this approach works best when the sub-process ends on it own.当我实施提供的解决方案时,我注意到这种方法在子流程自行结束时效果最佳。 But if the subprocess is providing a stream of information and we are looking for a single match of output, then that approach doesn't work for my needs (specifically for Windows, if that matters).但是,如果子进程提供信息流并且我们正在寻找输出的单个匹配项,那么该方法不适用于我的需要(特别是对于 Windows,如果这很重要)。

Here is my sample:这是我的示例:

File ping.py文件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()

File runner.py文件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")

My expectation is that the runner will make sure the process is started and then wait for the magic output and then stop, which it does.我的期望是 runner 将确保进程启动,然后等待魔术输出,然后停止,它确实如此。 However, the longer the sub-process runs, the longer the runner runs.但是,子流程运行的时间越长,运行程序运行的时间就越长。 But since the 'magic' output comes relatively quickly, I have to wait until the subprocess ends before I get anything processed.但由于“魔法”输出相对较快,我必须等到子进程结束才能处理任何内容。

What am I missing?我错过了什么?

OK, if I understand correctly what you are trying to do, the problem is with ping still being a child process to runner.好的,如果我正确理解您要做什么,问题在于 ping 仍然是运行程序的子进程。 While you can make read calls non-blocking, the parent process will not actually exit while the child is still running.虽然您可以使读取调用非阻塞,但当子进程仍在运行时,父进程实际上不会退出。 If you want runner not to wait for the child to finish, read the first line and the first magic output and then exit;如果你想让 runner 不等待孩子完成,读取第一行和第一个魔法输出然后退出; you need ping to disassociate itself from the parent process.您需要 ping 才能将自身与父进程分离。

Look at this code sample to see how that is done A simple Unix/Linux daemon in Python .查看此代码示例以了解其实现方式Python 中的简单 Unix/Linux 守护程序 Of course you might skip the part where they close and re-open all the I/O streams.当然,您可以跳过它们关闭并重新打开所有 I/O 流的部分。

On the same note, I am not sure leaving an open I/O stream connected to the parent will allow the parent to exit, so if that happens to be a problem you might have to figure out another way to exchange data.同样,我不确定保留连接到父级的开放 I/O 流是否会允许父级退出,因此如果这恰好是一个问题,您可能必须找出另一种交换数据的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM