7

Der folgende Code wird nicht gedruckt "here". Was ist das Problem? Ich testete es auf meinen beiden Maschinen (Windows 7, Ubuntu 12.10) und http://www.compileonline.com/execute_python_online.php Es druckt "here" in allen Fällen nicht.Skript, das Multiprozessormodul verwendet, wird nicht beendet

from multiprocessing import Queue, Process 


def runLang(que): 
    print "start" 
    myDict=dict() 
    for i in xrange(10000): 
     myDict[i]=i 
    que.put(myDict) 
    print "finish" 


def run(fileToAnalyze): 
    que=Queue() 
    processList=[] 
    dicList=[] 
    langs= ["chi","eng"] 
    for lang in langs: 
     p=Process(target=runLang,args=(que,)) 
     processList.append(p) 
     p.start() 

    for p1 in processList: 
     p1.join() 

    print "here" 

    for _ in xrange(len(langs)): 
     item=que.get() 
     print item 
     dicList.append(item) 

if __name__=="__main__": 
    processList = [] 
    for fileToAnalyse in ["abc.txt","def.txt"]: 
     p=Process(target=run,args=(fileToAnalyse,)) 
     processList.append(p) 
     p.start() 
    for p1 in processList: 
     p1.join() 

Antwort

13

Dies liegt daran, wenn Sie put viele Elemente in eine multiprocessing.Queue, sie im Speicher gepuffert schließlich bekommen, sobald die zugrunde liegende Pipe voll ist. Der Puffer wird nicht geleert, bis etwas vom anderen Ende des Queue zu lesen beginnt, was dem Pipe erlauben wird, mehr Daten zu akzeptieren. A Process kann nicht beendet werden, bis der Puffer für alle seine Queue Instanzen zu ihrem zugrunde liegenden Pipe vollständig gelöscht wurde. Die Implikation davon ist, dass, wenn Sie versuchen, join ein Prozess, ohne einen anderen Prozess/Thread aufrufen get auf Queue, Sie können Deadlock. Dies ist mentioned in the docs:

Warnung

Wie oben erwähnt, wenn ein Kind Prozesselemente in eine Warteschlange gestellt hat (und es nicht JoinableQueue.cancel_join_thread verwendet hat), dann ist das Verfahren nicht beenden, bis alle gepufferte Artikel wurden in die Pipe gespült.

Dies bedeutet, dass Sie einen Deadlock erhalten, wenn Sie versuchen, diesen Prozess beizutreten, es sei denn, Sie sind sicher, dass alle Elemente in der Warteschlange verbraucht worden sind. Wenn der untergeordnete Prozess nicht-dämonisch ist, kann der übergeordnete Prozess bei Beenden ebenfalls hängen bleiben, wenn es versucht, alle seine nicht-dämonischen untergeordneten Elemente beizutreten.

Beachten Sie, dass eine mit einem Manager erstellte Warteschlange dieses Problem nicht aufweist.

Sie können das Problem beheben, indem Sie nicht rufen join erst, nachdem Sie die Queue in der übergeordneten leeren:

for _ in xrange(len(langs)): 
    item = que.get() 
    print(item) 
    dicList.append(item) 

# join after emptying the queue. 
for p in processList: 
    p.join() 

print("here") 
Verwandte Themen