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

时间:2014-11-04 15:16:16

标签: python python-2.7 multiprocessing python-multiprocessing

以下代码不会打印"here"。问题是什么? 我在我的两台机器上测试了它(Windows 7,Ubuntu 12.10)和 http://www.compileonline.com/execute_python_online.php 在所有情况下都不会打印"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()

1 个答案:

答案 0 :(得分:14)

这是因为当你put multiprocessing.Queue多个项目时,一旦基础Pipe已满,它们最终会被缓存在内存中。在从Queue的另一端开始读取某些内容之前,缓冲区不会被刷新,这将允许Pipe接受更多数据。在Process个实例的缓冲区已完全刷新到其基础Queue之前,Pipe无法终止。这意味着如果你尝试join一个进程而没有另一个进程/线程在get上调用Queue,你可能会陷入僵局。这是mentioned in the docs

  

警告

     

如上所述,如果子进程已将项目放入队列(和   它没有使用JoinableQueue.cancel_join_thread),然后是那个过程   直到所有缓冲的项目都被刷新为止后才会终止   管。

     

这意味着如果您尝试加入该过程,您可能会陷入僵局   除非您确定所有已放入队列的项目   已被消耗。同样,如果子进程是非守护进程的   然后父进程在尝试加入所有进程时可能会在退出时挂起   非守护儿童。

     

请注意,使用管理器创建的队列没有此问题。

您可以在清空父级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")