2017-05-09 37 views
0

我已經編寫了一個小程序來啓動和停止從stdin讀取命令的子進程,使用gevent來希望高效地等待命令輸入和進程完成。用gevent和stdin管理一個子進程

它有一個命令R - 運行,它將stdin讀作一行。

R簡單的腳本sleep 2; echo "Hello, world!"開始SH如果尚未運行

有兩個greenlets,一個讀命令輸入和一個等待新的流程或等待當前進程完成。我使用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讀取文件的正確方法
  • 子進程等待事件未被正確使用,並且它永遠不會被喚醒。我還沒有見過這樣的例子,但Popen對象可以與gevent.wait一起使用,所以我認爲這是好的。
  • 如果我打破調試器堆棧跟蹤顯示正在等待從標準輸入讀取完成,我預計它會有一些select類似的行爲,並且當兩個greenlet正在等待的東西它會執行將繼續在greenlet首先完成。

回答

0

我對自己的問題有兩種解決方案。這些都將使我的示例程序按預期工作。

管stdin的

公開賽Popen(..., stdin=PIPE)子進程。它是有道理的,gevent不會工作,因爲它必須等待東西

使用FileObjectThread

這似乎不管如何創建子進程的工作,不知道爲什麼

相關問題