Je suis nouveau à python objet orienté et je réécrit mon application existante en tant que version orientée objet, car les développeurs sont en augmentation et que mon code est en train de devenir non sécurisé.
Normalement, j'utilise des files d'attente multiprocessionnaires, mais j'ai trouvé à partir de cet exemple http://www.doughellmann.com/pymotw/multiprorocessing/basics.html que je peux sous-classement multiprocessing.Process
Alors je pense que c'est un Bonne idée et j'ai écrit une classe à tester comme ceci:
code:
from multiprocessing import Process
class Processor(Process):
def return_name(self):
return "Process %s" % self.name
def run(self):
return self.return_name()
processes = []
if __name__ == "__main__":
for i in range(0,5):
p=Processor()
processes.append(p)
p.start()
for p in processes:
p.join()
Cependant, je ne peux pas récupérer les valeurs, comment puis-je utiliser des files d'attente de cette manière?
Edit: Je veux obtenir la valeur de retour et penser où mettre Queues()
.
multiprocessing.Process
:Cependant, je ne peux pas récupérer les valeurs, comment puis-je utiliser des files d'attente de cette manière?
Le processus nécessite une Queue()
pour recevoir les résultats ... Un exemple de la sous-classe multiprocessing.Process
Suit ...
from multiprocessing import Process, Queue
class Processor(Process):
def __init__(self, queue, idx, **kwargs):
super(Processor, self).__init__()
self.queue = queue
self.idx = idx
self.kwargs = kwargs
def run(self):
"""Build some CPU-intensive tasks to run via multiprocessing here."""
hash(self.kwargs) # Shameless usage of CPU for no gain...
## Return some information back through multiprocessing.Queue
## NOTE: self.name is an attribute of multiprocessing.Process
self.queue.put("Process idx={0} is called '{1}'".format(self.idx, self.name))
if __name__ == "__main__":
NUMBER_OF_PROCESSES = 5
## Create a list to hold running Processor object instances...
processes = list()
q = Queue() # Build a single queue to send to all process objects...
for i in range(0, NUMBER_OF_PROCESSES):
p=Processor(queue=q, idx=i)
p.start()
processes.append(p)
# Incorporating ideas from this answer, below...
# https://stackoverflow.com/a/42137966/667301
[proc.join() for proc in processes]
while not q.empty():
print "RESULT: {0}".format(q.get()) # get results from the queue...
Sur ma machine, cela se traduit par ...
$ python test.py
RESULT: Process idx=0 is called 'Processor-1'
RESULT: Process idx=4 is called 'Processor-5'
RESULT: Process idx=3 is called 'Processor-4'
RESULT: Process idx=1 is called 'Processor-2'
RESULT: Process idx=2 is called 'Processor-3'
$
multiprocessing.Pool
:FWIW, un désavantage que j'ai trouvé au sous-classement multiprocessing.Process
Est que vous ne pouvez pas tirer parti de toute la bonté intégrée de multiprocessing.Pool
; Pool
vous donne une très belle API si vous ne le faites pas besoin votre producteur et votre code de consommateur à se parler à une file d'attente.
Vous pouvez faire beaucoup de choses avec quelques valeurs de retour créatives ... dans l'exemple suivant, j'utilise une dict()
pour encapsuler les valeurs d'entrée et de sortie de pool_job()
...
from multiprocessing import Pool
def pool_job(input_val=0):
# FYI, multiprocessing.Pool can't guarantee that it keeps inputs ordered correctly
# dict format is {input: output}...
return {'pool_job(input_val={0})'.format(input_val): int(input_val)*12}
pool = Pool(5) # Use 5 multiprocessing processes to handle jobs...
results = pool.map(pool_job, xrange(0, 12)) # map xrange(0, 12) into pool_job()
print results
Il en résulte:
[
{'pool_job(input_val=0)': 0},
{'pool_job(input_val=1)': 12},
{'pool_job(input_val=2)': 24},
{'pool_job(input_val=3)': 36},
{'pool_job(input_val=4)': 48},
{'pool_job(input_val=5)': 60},
{'pool_job(input_val=6)': 72},
{'pool_job(input_val=7)': 84},
{'pool_job(input_val=8)': 96},
{'pool_job(input_val=9)': 108},
{'pool_job(input_val=10)': 120},
{'pool_job(input_val=11)': 132}
]
De toute évidence, il y a beaucoup d'autres améliorations à apporter dans pool_job()
, telle que la manipulation des erreurs, mais cela illustre l'essentiel. FYI, Cette réponse Fournit un autre exemple de comment utiliser multiprocessing.Pool
.
Merci beaucoup tout le monde.
Maintenant, voici comment je l'ai fait :)
Dans cet exemple, j'utilise plusieurs Queus, car je ne veux pas communiquer entre chaque Ohter, mais uniquement avec le processus parent.
from multiprocessing import Process,Queue
class Processor(Process):
def __init__(self,queue):
Process.__init__(self)
self.que=queue
def get_name(self):
return "Process %s" % self.name
def run(self):
self.que.put(self.get_name())
if __name__ == "__main__":
processes = []
for i in range(0,5):
p=Processor(Queue())
processes.append(p)
p.start()
for p in processes:
p.join()
print p.que.get()
La valeur de retour de Process.run
ne va nulle part. Vous devez les renvoyer au processus parent, par exemple. utilisant un multiprocessing.Queue
( docs ici ).
Réponse de Mike est le meilleur, mais juste pour la complétude, je veux mentionner que je préfère Récupérez la file d'attente de join
contextes Donc, le dernier bit ressemblerait à ceci:
[proc.join() for proc in processes] # 1. join
while not q.empty(): # 2. get the results
print "RESULT: %s" % q.get()