producteur/consommateur problème avec python multitraitement
Je suis en train d'écrire un programme serveur avec une producteurs et plusieurs consommateurs,
ce qui me confond est que la première tâche producteur a mis dans la file d'attente devient
consommé, après les tâches en file d'attente ne reçoivent plus consommés, ils restent
dans la file d'attente pour toujours.
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()
Le producteur est un serveur HTTP qui a mis une tâche dans la file d'attente une fois que recevoir
une demande de l'utilisateur. Il semble que les consommateurs processus sont encore
bloqué quand il y a de nouvelles tâches dans la file d'attente, ce qui est étrange.
P. S. un Autre deux questions ne se rapportant pas à la ci-dessus, je ne suis pas sûr si
c'est mieux de mettre du serveur HTTP dans son propre processus autres que la principale
processus, si oui comment puis-je rendre le processus principal de continuer à courir avant tous
les enfants des processus de fin. Deuxième question, quel est le meilleur moyen d'arrêter la
Serveur HTTP gracieusement?
Modifier: ajouter le code du fabricant, c'est juste une simple python serveur 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()
Vous devez vous connecter pour publier un commentaire.
Je pense qu'il doit y avoir quelque chose de mal avec le serveur web de la partie, comme cela fonctionne parfaitement:
Exemple de sortie:
queue.close()
àself.queue.close()
pour faire référence à la droite de la file d'attente"Deuxième question, quelle est la meilleure façon d'arrêter le serveur HTTP gracieusement?"
C'est dur.
Vous avez deux choix pour la Communication Interprocessus:
Extérieur de la bande de contrôle. Le serveur a un autre mécanisme pour la communication. Une autre socket Unix Signal, ou quelque chose d'autre. L'autre chose qui pourrait être un "stop-maintenant" fichier dans le serveur de répertoire local. Semble étrange, mais il fonctionne bien et est plus simple que de présenter une sélection de boucle à écouter sur plusieurs sockets ou un gestionnaire de signal pour attraper un service de l'information du signal.
Le "stop-maintenant" le fichier est facile à mettre en œuvre. Le
evwsgi.run()
boucle simplement vérifie ce fichier après chaque demande. Pour faire l'arrêt du serveur, vous créez le fichier, exécuter une/control
demande (qui sera une erreur 500 ou quelque chose, il n'a pas vraiment d'importance) et le serveur devrait stagner. N'oubliez pas de supprimer le point d'arrêt maintenant fichier, sinon votre serveur ne redémarre pas.Dans la bande de contrôle. Le serveur a une autre URL (
/stop
) qui va l'arrêter. Superficiellement, il semble que la sécurité cauchemar, mais tout dépend où et comment ce serveur sera utilisé. Puisqu'il semble être un simple wrapper autour de la demande interne à la file d'attente, ce supplément d'URL fonctionne bien.Pour faire ce travail, vous devez écrire votre propre version de
evwsgi.run()
qui peuvent être résiliés par le réglage de certaines variables dans une manière qui permettra de sortir de la boucle.Modifier
Vous ne voulez probablement pas à mettre fin à votre serveur, car vous ne connaissez pas l'état de ses threads. Vous devez signaler le serveur et ensuite vous avez juste à attendre jusqu'à ce qu'il termine les choses normalement.
Si vous souhaitez forcer tuer le serveur, puis
os.kill()
(oumultiprocessing.terminate
) fonctionne. Sauf, bien sûr, vous ne savez pas ce que l'enfant fils étaient en train de faire.Cela peut aider:
http://www.rsdcbabu.com/2011/02/multiprocessing-with-python.html