6

我正在尝试在 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

我究竟做错了什么?

谢谢。

附带说明:如果我的脚本有什么可以改进的地方,请告诉我。简单的事情,例如检查队列何时为空等。

4

2 回答 2

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()
于 2012-02-08T14:34:22.383 回答
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 来做这种模式。

于 2012-02-08T20:13:45.063 回答