2015-05-18 6 views
7

Wenn ich Queue.Queue verwende, funktioniert meine read() Funktion nicht, warum? Aber wenn ich multiprocessing.Queue verwenden, es funktioniert gut:multiprocessing.Queue und Queue.Queue sind anders?

from multiprocessing import Pool, Process, Queue 
import os, time 
# from Queue import Queue 

def write(q): 
    for v in ['A', 'B', 'C']: 
     print 'Put %s to queue ' % v 
     q.put_nowait(v) 
     time.sleep(0.2) 

def read(q): 
    while 1: 
     if not q.empty(): 
      v = q.get(True) 
      print "Get %s from queue" % v 
      time.sleep(0.2) 
     else: 
      break 

if __name__ == '__main__': 
    q = Queue() 
    pw = Process(target=write, args=(q,)) 
    pr = Process(target=read, args=(q,)) 
    pw.start() 
    pw.join() 

    pr.start() 
    pr.join() 

    print "all done..." 
+2

Denken Sie darüber nach: Wenn sie _weren_ nicht anders sind, warum würde 'multiprocessing.Queue' überhaupt existieren? Der springende Punkt ist, Ihnen ein 'queue.Queue'-ähnliches Objekt zu geben, das auch zwischen getrennten Prozessen funktioniert. – abarnert

Antwort

19

Queue.Queue ist nur eine In-Memory-Warteschlange, die weiß, wie man mit mehreren Threads behandeln es zugleich verwenden. Es funktioniert nur, wenn sowohl der Produzent als auch der Verbraucher im selben Prozess sind.

Sobald Sie sie in separaten Systemprozessen haben, was die Bibliothek multiprocessing ist, sind die Dinge ein wenig komplizierter, weil die Prozesse nicht mehr den gleichen Speicher teilen. Sie benötigen eine Art Interprozess-Kommunikationsmethode, damit die beiden Prozesse miteinander kommunizieren können. Es kann ein gemeinsamer Speicher sein, eine Pipe oder ein Socket oder möglicherweise etwas anderes. Dies ist, was multiprocessing.Queue tut. Es verwendet Pipes, um zwei Prozessen die Kommunikation zu ermöglichen. Es wird einfach die gleiche API wie Queue.Queue implementiert, da die meisten Python-Programmierer bereits damit vertraut sind.

Beachten Sie auch, dass die Art, wie Sie die Warteschlange verwenden, in Ihrem Programm eine Race-Bedingung hat. Denken Sie darüber nach, was passiert, wenn der Prozess write in die Warteschlange schreibt, nachdem Sie q.empty() im Prozess read aufgerufen haben. Normalerweise würden Sie der Warteschlange ein spezielles Element hinzufügen (z. B. None), was bedeuten würde, dass der Verbraucher anhalten kann.

+0

Ich habe q.empty() für Multiprocessing.Queue * extrem * unzuverlässig gefunden. Es ist öfter falsch, ehrlich gesagt, es ist richtig. Nicht einmal ein Race-Condition-Problem: Sie können Prozess A etwas in die Warteschlange stecken lassen, wenn Prozess B schläft, und später leer() von Prozess B aufrufen - es meldet sich leer, egal wie lange das Element dort gewartet hat. Eine viel bessere Option ist zu prüfen, ob qsize()> 0 - das ist nicht perfekt, aber * viel * konsequenter korrekt. –

+0

Ein FYI in Bezug auf Multiprocessing.Queue (als eine Verhaltensdifferenz über Warteschlange.Queue): Daten in die Warteschlange * eingefügt * müssen * ausgelesen werden. Wenn ein Prozess in eine Warteschlange schreibt und später beendet wird, wird er erst beendet, wenn ein anderer Prozess das Element der Warteschlange akzeptiert. –

Verwandte Themen