使用 gevent 和 stdin 管理子进程

Managing a subprocess with gevent and stdin

我编写了一个小程序来根据从标准输入读取的命令启动和停止子进程,希望使用 gevent 有效地等待命令输入和进程完成。

它有一个命令 R - 运行,它将标准输入读取为一行。

R 如果它还没有 运行ning

,只需使用脚本 sleep 2; echo "Hello, world!" 启动 sh

有两个greenlet,一个读取命令输入,一个等待新进程或等待当前进程完成。我使用 gevent Event 在两者之间切换。

我的问题:进程的 greenlet 永远不允许完成。命令 greenlet 似乎总是 运行ning 并且从不放弃控制。为什么进程 greenlet 永远不会从等待中醒来,即使进程明显已完成?

来源如下:

import sys
from gevent import spawn, joinall, sleep
from gevent.subprocess import Popen
from gevent.fileobject import FileObjectPosix
from gevent.event import Event

process = None
trigger = Event()

def start_process():
    global process
    process = Popen(['/bin/sh', '-c', 'sleep 2; echo Hello, World!'])

def wait_process():
    global process
    while True:
        trigger.wait()
        print('INFO - Awaiting new process')
        trigger.clear()
        process.wait()
        process = None
        print('INFO - Process done')

def get_input():
    global process
    stdin_wrapped = FileObjectPosix(sys.stdin)
    while True:
        line = stdin_wrapped.readline().decode().strip()
        if line == 'R':
            if not process:
                start_process()
                trigger.set()
                print('OK - Running process')

            else:
                print('FAIL - Process already running')
        sleep(0)

def main():
    joinall([
        spawn(get_input),
        spawn(wait_process)
    ])

if __name__ == '__main__':
    main()

会话看起来像这样,Rs 之间有 >2s 的间隔:

R
OK - Running process
INFO - Awaiting new process
Hello, World!
R
FAIL - Process already running

我希望看到:

R
OK - Running process
INFO - Awaiting new process
Hello, World!
INFO - Process done
R
OK - Running process

我最初的想法是两个错误之一:

对于我自己的问题,我有两种解决方案。这些中的任何一个都会使我的示例程序按预期运行。

标准输入管道

Popen(..., stdin=PIPE) 打开子流程。没有它 gevent 将无法工作是有道理的,因为它必须等待 something.

使用FileObjectThread

无论子流程如何创建,这似乎都有效,不确定为什么