使用多处理模块的脚本不会终止
下面的代码,不打印"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")