我正在尝试在Gevent中建立一个简单的生产者 - 消费者系统,但我的脚本不会退出:
import gevent
from gevent.queue import *
import time
import random
q = Queue()
workers = []
def do_work(wid, value):
"""
Actual blocking function
"""
gevent.sleep(random.randint(0,2))
print 'Task', value, 'done', wid
return
def worker(wid):
"""
Consumer
"""
while True:
item = q.get()
do_work(wid, item)
def producer():
"""
Producer
"""
for i in range(4):
workers.append(gevent.spawn(worker, random.randint(1, 100000)))
for item in range(1, 9):
q.put(item)
producer()
gevent.joinall(workers)
我无法找到关于使用Gevent的优秀示例/教程,所以我上面粘贴的是我从互联网上拼凑出的内容。
多个工作程序被激活,项目进入队列,但即使队列中的所有内容都完成,主程序也不会退出。我必须按CTRL ^ C
。
我做错了什么?
感谢。
旁注:如果我的脚本有任何可以改进的地方,请告诉我。简单的事情,例如检查队列何时为空,等等。
答案 0 :(得分:5)
我认为你应该像文档中的示例一样使用JoinableQueue
。
import gevent
from gevent.queue import *
import time
import random
q = JoinableQueue()
workers = []
def do_work(wid, value):
gevent.sleep(random.randint(0,2))
print 'Task', value, 'done', wid
def worker(wid):
while True:
item = q.get()
try:
do_work(wid, item)
finally:
q.task_done()
def producer():
for i in range(4):
workers.append(gevent.spawn(worker, random.randint(1, 100000)))
for item in range(1, 9):
q.put(item)
producer()
q.join()
答案 1 :(得分:2)
在你的工作者中,你激活一个永远运行的循环。
作为旁注,一个更优雅的“永远循环”可以写成:
for work_unit in q:
# Do work, etc
gevent.joinall()等待工人完成;但他们永远不会这样做,所以你的计划将永远等待。这就是导致它不退出的原因。
如果你不再关心工人了,你可以改为杀死他们:
gevent.killall(workers)
另一种方法是在队列中放置一个“特殊”项。当工人收到此项目时,它会将其识别为与正常工作不同并停止工作。
for worker in workers:
q.put("TimeToDie")
for work_unit in q:
if work_unint == "TimeToDie":
break
do_work()
或者你甚至可以使用gevent的Event来做这种模式。