2017-04-16 1 views
10

Ich habe eine einfache Aufgabe wie folgt aus:.Python multiprocessing.Queue vs multiprocessing.manager() Queue()

def worker(queue): 
    while True: 
     try: 
      _ = queue.get_nowait() 
     except Queue.Empty: 
      break 

if __name__ == '__main__': 
    manager = multiprocessing.Manager() 
    # queue = multiprocessing.Queue() 
    queue = manager.Queue() 

    for i in range(5): 
     queue.put(i) 

    processes = [] 

    for i in range(2): 
     proc = multiprocessing.Process(target=worker, args=(queue,)) 
     processes.append(proc) 
     proc.start() 

    for proc in processes: 
     proc.join() 

Es scheint, dass multiprocessing.Queue alle Arbeit tun können, was ich brauchte, aber auf der anderen Hand Ich sehe viele Beispiele für Manager(). Queue() und kann nicht verstehen, was ich wirklich brauche. Sieht aus wie Manager(). Queue() verwendet eine Art von Proxy-Objekten, aber ich verstehe diesen Zweck nicht, da multiprocessing.Queue() die gleiche Arbeit ohne Proxy-Objekte ausführt.

Also, meine Fragen sind:

1) Was wirklich Unterschied zwischen multiprocessing.Queue und Objekt durch multiprocessing.manager() zurück Queue().?

2) Was muss ich verwenden?

+3

Dies könnte hilfreich sein. https://code.activestate.com/lists/python-tutor/99586/ –

Antwort

8

Obwohl mein Verständnis ist, über dieses Thema beschränkt, von dem, was ich tat, ich sagen kann zwischen multiprocessing.Queue() und multiprocessing.Manager() Queue() gibt einen Hauptunterschied ist.

  • Multiprozessing. Queue() ist ein Objekt, während multiprocessing.Manager(). Queue() ist eine Adresse (Proxy), die auf eine gemeinsam genutzte Warteschlange verweist, die vom multiprocessing.Manager() - Objekt verwaltet wird.
  • daher können Sie normale multiprocessing.Queue() - Objekte nicht an Pool-Methoden übergeben, da sie nicht gebeizt werden können.
  • Darüber hinaus ist die python doc sagen uns, besondere Aufmerksamkeit zu zahlen, wenn multiprocessing.Queue() verwendet, weil es unerwünschte Effekte

Hinweis hat Wenn ein Objekt in einer Warteschlange gestellt wird, wird das Objekt gebeizt und Ein Hintergrundthread spült später die gebeizten Daten zu einer zugrunde liegenden Pipe. Dies hat einige Konsequenzen, die ein wenig überraschend sind, aber keine praktischen Schwierigkeiten verursachen sollten - wenn sie Sie wirklich stören, können Sie stattdessen eine mit einem Manager erstellte Warteschlange verwenden. Nachdem ein Objekt in eine leere Warteschlange gestellt wurde, kann es eine infinitesimale Verzögerung geben, bevor die empty() - Methode der Warteschlange False zurückgibt und get_nowait() zurückkehren kann, ohne dass Queue.Empty ausgelöst wird. Wenn mehrere Prozesse Objekte in die Warteschlange stellen, ist es möglich, dass die Objekte am anderen Ende außerhalb der Reihenfolge empfangen werden. Objekte, die in den gleichen Prozess eingereiht werden, befinden sich jedoch immer in der erwarteten Reihenfolge.

Warnung Wie oben erwähnt, wenn ein Kind Prozesselemente in eine Warteschlange gestellt hat (und es nicht verwendet JoinableQueue.cancel_join_thread hat), dann beenden, dass der Prozess nicht, bis alle gepufferten Elemente an das Rohr gespült wurden. Dies bedeutet, dass Sie einen Deadlock erhalten, wenn Sie versuchen, an diesem Prozess teilzunehmen, es sei denn, Sie sind sicher, dass alle Artikel, die in die Warteschlange gestellt wurden, verbraucht wurden. Wenn der Child-Prozess nicht-dämonisch ist, kann der Elternprozess beim Beenden hängen bleiben, wenn er versucht, all seinen nicht-dämonischen Kindern beizutreten. Beachten Sie, dass eine mit einem Manager erstellte Warteschlange dieses Problem nicht aufweist.

Es gibt eine Abhilfe multiprocessing.Queue() mit Pool zu verwenden, indem die Warteschlange als globale Variable einstellen und es für alle Prozesse bei der Initialisierung Einstellung:

queue = multiprocessing.Queue() 
def initialize_shared(q): 
    global queue 
    queue=q 

pool= Pool(nb_process,initializer=initialize_shared, initargs(queue,)) 

Prozesse korrekt schaffen wird Pool mit geteiltem Warteschlangen, aber wir können argumentieren, dass die multiprocessing.Queue() - Objekte nicht für diese Verwendung erstellt wurden.

Auf der anderen Seite kann die manager.Queue() zwischen Pool-Subprozessen geteilt werden, indem sie als normales Argument einer Funktion übergeben wird.

Meiner Meinung nach, mit multiprocessing.Manager(). Queue() ist in jedem Fall in Ordnung und weniger mühsam. Es kann einige Nachteile mit einem Manager geben, aber ich bin mir dessen nicht bewusst.

Verwandte Themen