python多处理自助消费者永远锁定

时间:2011-10-31 19:19:44

标签: python process queue multiprocessing

问题在于消费者永远不会退出,只是挂起无所事事。代码的目的是这样:

创建一个队列,并将一些task_data传递给它。创建指定数量的使用者以处理数据。当消费者发现队列为空时,因为其他消费者仍有可能将某些东西放入队列,但它不能离开,但是它可以在consumers_finished列表中指出它没有作业。消费者循环继续,直到每个工人都表明他们完成了工作。目前尚不清楚将会有多少工作,因为消费者将任务放入队列。我读到了一些关于这一点的内容,但是如果他们自己养活的话,流程是否可以永远等待,我不清楚。

class Consumer(multiprocessing.Process):

    def __init__(self, task_queue, results, consumers_finished):
        multiprocessing.Process.__init__(self)
        self.task_queue = task_queue
        self.results = results
        self.consumers_finished = consumers_finished

    def run(self):
        while not all(flag for flag in self.consumers_finished.values()):
            task_data = self.task_queue.get()
            if not task_data:
                self.consumers_finished[self.name] = True
                continue

            self.consumers_finished[self.name] = False
            task_result = self.do_some_processing(task_data)
            self.task_queue.put(task_result)


class Starter(object):

    def start(self):
        manager = multiprocessing.Manager()
        task_queue = multiprocessing.Queue()
        results = manager.list()
        consumers_finished = manager.dict()

        consumers = [Consumer(task_queue, results, consumers_finished) for i in range(self.consumers_count)]

        for consumer in consumers:
            consumers_finished[consumer.name] = False
            consumer.start()

        task_queue.put(task_data)

        for consumer in consumers: consumer.join()

        return results

1 个答案:

答案 0 :(得分:2)

看起来好好的睡眠确实有帮助,精神焕发的心灵可以做得更多.. 无论如何,我在研究了python文档之后找到了解决方案。

class Consumer(multiprocessing.Process):

    def __init__(self, task_queue, results, consumers_finished):
        multiprocessing.Process.__init__(self)
        self.task_queue = task_queue
        self.results = results
        self.consumers_finished = consumers_finished

    def run(self):
        while not all(flag for flag in self.consumers_finished.values()):
            try:
                task = self.todo_queue.get(False)
                self.consumers_finished[self.name] = False
            except QueueEmpty:
                self.consumers_stopped[self.name] = True
                continue

            task_result = self.do_some_processing(task_data)
            self.task_queue.put(task_result)


class Starter(object):

    def start(self):
        manager = multiprocessing.Manager()
        task_queue = manager.Queue()
        results = manager.list()
        consumers_finished = manager.dict()

        consumers = [Consumer(task_queue, results, consumers_finished) for i in range(self.consumers_count)]

        for consumer in consumers:
            consumers_finished[consumer.name] = False
            consumer.start()

        task_queue.put(task_data)

        for consumer in consumers: consumer.join()

        return results

这是python文档的一部分,它解释了我的问题:

  

警告如上所述,如果子进程已将项目放在a上   然后,队列(并且它没有使用JoinableQueue.cancel_join_thread())   在所有缓冲项都存在之前,该进程不会终止   冲到管道上。这意味着如果您尝试加入该流程   你可能会陷入僵局,除非你确定所有的项目都有   被放在队列上已被消耗。同样,如果孩子   进程是非守护进程,然后父进程可能会在退出时挂起   它试图加入所有非守护儿童。 请注意一个队列   使用经理创建的没有此问题。请参阅编程   准则。

所以我刚刚更改了队列,它现在由管理员创建,而在消费者的运行方法中,任务以不同的方式从队列中获取,请参阅代码。