使用多处理模块的脚本不会终止

下面的代码,不打印"here" 。 问题是什么? 我在我的两台机器(Windows 7,Ubuntu 12.10)和http://www.compileonline.com/execute_python_online.php上testing了它,在所有情况下都不打印"here"

 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() 

这是因为当你put大量的项目放到一个multiprocessing.Queue中时,一旦底层Pipe已满,它们最终会被caching在内存中。 缓冲区不会刷新,直到从Queue的另一端开始读取,这将允许Pipe接受更多的数据。 Process无法终止,直到其所有Queue实例的缓冲区已完全刷新到其基础Pipe 。 这意味着如果你尝试join一个进程而没有另一个进程/线程调用get它的Queue ,你可能会死锁。 这在文档中提到 :

警告

如上所述,如果subprocess已经将项目放入队列(并且没有使用JoinableQueue.cancel_join_thread ),那么在所有缓冲项目已经刷新到pipe道之前,该进程不会终止。

这意味着如果你尝试join这个过程,你可能会遇到一个死锁,除非你确定已经放在队列中的所有物品都已经被消耗掉了。 同样,如果subprocess是非守护进程,那么父进程在尝试join其所有非守护进程subprocess时可能会挂起。

请注意,使用pipe理器创build的队列不存在此问题。

您可以通过不调用join来解决问题,直到您清空父项中的Queue后:

 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")