如何(gevent)在不等待它加入的情况下产生任务

问题描述:

我写了一个我的问题的示例代码。我正在生成一个随机字符串和一个shuffle函数,它为消息添加了一个延迟,所以它以不同的顺序出现。如何(gevent)在不等待它加入的情况下产生任务

但是,计划任务只有在末尾有joinall后才会执行。有没有办法在动态调度新产卵的时候执行调度和任务。当我一直按下Enter键时,它会安排一项新任务,但在我达到我设定的随机条件之前,它不会执行。但是,如果我在追加后放置join/joinall,它会阻止。这可能与gevent有关,还有其他什么库可以用其他异步I/O或非阻塞库来完成,或者我必须使用多线程。

#!/usr/bin/python 
import random 
import string 
from gevent import sleep, spawn, joinall 

def random_string(): 
    digits = "".join([random.choice(string.digits) for i in xrange(8)]) 
    chars = "".join([random.choice(string.letters) for i in xrange(10)]) 
    return chars 

def delay_message(message, delay): 
    sleep(delay) 
    print("Shuffled message: {} and time: {}". format(message, delay)) 

def main(): 
    while True: 
     s = raw_input("Please continue pressing enter, messages will appear when they are ready") 
     if s == "": 
      delay = random.randint(0, 10) 
      string = random_string() 
      print("Message: {} and time: {}". format(string, delay)) 
      tasks = [] 
      tasks.append(spawn(delay_message, string, delay)) 

      if (random.randint(0,10) == 5): # random condition in breaking 
       joinall(tasks, raise_error=True) 
       break 
     else: 
      print("Exiting") 
      break 

if __name__ == "__main__": 
    main() 
+0

'raw_input'是一个* blocking *操作系统调用。 gevent是合作的,所以当主greenlet卡在'raw_input'中时*没有其他greenlet可以运行*。这是你的实际代码,你有问题,或者你简化它包含'raw_input'? –

+0

@JasonMadden代替'raw_input',它会是'sock.recv()',而不是在delay_message处打印,我会'sendall()'。这仍然会造成问题吗? – Anderson

+0

除非你很早就对系统进行了猴子修补,或者是专门导入和使用gevent的套接字类,是的,那些仍然会阻塞会导致这个问题的调用。 –

我发现了一个解决方案:使用ThreadPool例如tasks = ThreadPool(25)分配外循环并删除tasks=[]joinall()

此外,添加from gevent import wait然后在休息前while循环随机条件添加wait(),从而退出程序之前,现有的任务可以完成

+0

所以如果你monkeypatch,正常的事情变成gevent屈服事件,如睡眠和io阅读...... –

无论您是否加入,您都可以完成工作,您只需在需要确保工作完成之前加入以确保并发性,您可以使用大量方法获取状态(队列,共享变量,回调,委托方法),因为你使用的是greenlet,你甚至不需要像添加数字那样锁定原子操作,因为它们正在发生同一个线程。