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

以下代码不打印"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()


波斯汪
浏览 279回答 1
1回答

料青山看我应如是

这是因为,当您将put许多项目放入时multiprocessing.Queue,一旦底层Pipe已满,它们最终将被缓冲在内存中。在从的另一端开始读取内容之前,不会刷新缓冲区Queue,这将允许Pipe接受更多数据。Process在所有Queue实例的缓冲区完全刷新到其底层之前,A 无法终止Pipe。这个含义是,如果你尝试join的过程,而无需另一个进程/线程调用get它Queue,你可以死锁。在文档中提到了这一点:警告如上所述,如果子进程已将项目放入队列中(并且尚未使用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")
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python