我编写了一个小程序来启动和停止从stdin读取命令的子进程,使用gevent,希望有效地等待命令输入和进程完成。
它有一个命令R
- 运行,它将stdin读作一行。
R
只需使用脚本sleep 2; echo "Hello, world!"
启动,如果它尚未运行
有两个greenlet,一个读取命令输入,一个等待新进程或等待当前进程完成。我使用gevent Event
在两者之间切换。
我的问题:该过程的greenlet永远不会允许完成。命令greenlet似乎始终在运行,并且永远不会放弃控制。为什么进程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()
会话看起来像这样,R
s之间的差距> 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
我最初的想法是出现两个问题之一:
gevent.wait
一起使用所以我认为这没问题。select
的行为,当两个greenlet正在等待它会执行时在第一个完成的greenlet中恢复。答案 0 :(得分:0)
我对自己的问题有两个解决方案。这些中的任何一个都会使我的示例程序按预期运行。
使用Popen(..., stdin=PIPE)
打开子流程。如果没有它,gevent将无法工作,因为它必须等待某事。
FileObjectThread
无论子进程是如何创建的,这似乎都有效,不知道为什么