python多处理的生产者/消费者问题

btw*_*tw0 14 python multiprocessing

我正在编写一个服务器程序,其中包含一个生产者和多个消费者,让我感到困惑的只是生成器放入队列的第一个任务被消耗,之后排队的任务不再被消耗,它们永远保留在队列中.

from multiprocessing import Process, Queue, cpu_count
from http import httpserv
import time

def work(queue):
    while True:
        task = queue.get()
        if task is None:
            break
        time.sleep(5)
        print "task done:", task
    queue.put(None)

class Manager:
    def __init__(self):
        self.queue = Queue()
        self.NUMBER_OF_PROCESSES = cpu_count()

    def start(self):
        self.workers = [Process(target=work, args=(self.queue,))
                        for i in xrange(self.NUMBER_OF_PROCESSES)]
        for w in self.workers:
            w.start()

        httpserv(self.queue)

    def stop(self):
        self.queue.put(None)
        for i in range(self.NUMBER_OF_PROCESSES):
            self.workers[i].join()
        queue.close()

Manager().start()
Run Code Online (Sandbox Code Playgroud)

生产者是HTTP服务器,一旦接收到用户的请求,就将任务放入队列中.当队列中有新任务时,消费者进程似乎仍然被阻止,这很奇怪.

PS另外两个与上述问题无关的问题,我不确定将HTTP服务器放在除主流程之外的其他进程中是否更好,如果是,如何在所有子进程结束之前使主进程继续运行.第二个问题,什么是优雅地停止HTTP服务器的最佳方法?

编辑:添加生产者代码,它只是一个简单的python wsgi服务器:

import fapws._evwsgi as evwsgi
from fapws import base

def httpserv(queue):
    evwsgi.start("0.0.0.0", 8080)
    evwsgi.set_base_module(base)

    def request_1(environ, start_response):
        start_response('200 OK', [('Content-Type','text/html')])
        queue.put('task_1')
        return ["request 1!"]

    def request_2(environ, start_response):
        start_response('200 OK', [('Content-Type','text/html')])
        queue.put('task_2')
        return ["request 2!!"]

    evwsgi.wsgi_cb(("/request_1", request_1))
    evwsgi.wsgi_cb(("/request_2", request_2))

    evwsgi.run()
Run Code Online (Sandbox Code Playgroud)

Lup*_*uch 11

我认为Web服务器部分一定有问题,因为这完美地工作:

from multiprocessing import Process, Queue, cpu_count
import random
import time


def serve(queue):
    works = ["task_1", "task_2"]
    while True:
        time.sleep(0.01)
        queue.put(random.choice(works))


def work(id, queue):
    while True:
        task = queue.get()
        if task is None:
            break
        time.sleep(0.05)
        print "%d task:" % id, task
    queue.put(None)


class Manager:
    def __init__(self):
        self.queue = Queue()
        self.NUMBER_OF_PROCESSES = cpu_count()

    def start(self):
        print "starting %d workers" % self.NUMBER_OF_PROCESSES
        self.workers = [Process(target=work, args=(i, self.queue,))
                        for i in xrange(self.NUMBER_OF_PROCESSES)]
        for w in self.workers:
            w.start()

        serve(self.queue)

    def stop(self):
        self.queue.put(None)
        for i in range(self.NUMBER_OF_PROCESS):
            self.workers[i].join()
        self.queue.close()


Manager().start()
Run Code Online (Sandbox Code Playgroud)

样本输出:

starting 2 workers
0 task: task_1
1 task: task_2
0 task: task_2
1 task: task_1
0 task: task_1
Run Code Online (Sandbox Code Playgroud)