为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

波斯汪 2019-11-20 11:02:10
以下代码不打印"here"。问题是什么?我测试了它在两个我的机器(Windows 7中,Ubuntu的12.10),和 http://www.compileonline.com/execute_python_online.php 它不打印"here"在所有情况下。from multiprocessing import Queue, Processdef 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 回答

?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

这是因为,当您将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")


查看完整回答
反对 回复 2019-11-20
  • 1 回答
  • 0 关注
  • 278 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信