多处理在Windows中加入

时间:2016-01-21 22:55:34

标签: windows python-3.x queue multiprocessing

我有一个脚本,可以从数据库中收集数据,过滤并放入列表中进行进一步处理。我在几个进程之间拆分数据库中的条目,以使过滤更快。这是片段:

def get_entry(pN,q,entries_indicies):

    ##collecting and filtering data
    q.put((address,page_text,))
    print("Process %d finished!" % pN)

def main():

    #getting entries
    data = []

    procs = []
    for i in range(MAX_PROCESSES):
        q = Queue()
        p = Process(target=get_entry,args=(i,q,entries_indicies[i::MAX_PROCESSES],))
        procs += [(p,q,)]
        p.start()       
    for i in procs:
        i[0].join()
        while not i[1].empty():
            #process returns a tuple (address,full data,)
            data += [i[1].get()]
    print("Finished processing database!")

    #More tasks
    #................

我在Linux(Ubuntu 14.04)上运行它,它完全没问题。当我在Windows 7上运行它时,问题就开始了。脚本在i[0].join()上停留在16个进程中的第11个进程(对我来说看起来完全随机)。没有错误消息,没有,只是在那里冻结。同时,显示所有进程的print("Process %d finished!" % pN),这意味着它们都已结束,因此get_entry的代码应该没有问题

我尝试在流程函数中对q.put行进行评论,但这一切都很顺利(当然,data最终为空)。

这是否应该归咎于Queue?为什么会让join()卡住?是因为Lock内的内部Queue吗?如果是这样,如果Queue使我的脚本在Windows上无法使用,是否有其他方法可以将进程收集的数据传递给主进程中的data列表?

2 个答案:

答案 0 :(得分:0)

得到了我上一个问题的答案。

我使用Manager代替

def get_entry(pN,q,entries_indicies):
    #processing

    # assignment to manager list in another process doesn't work, but appending does.
    q += result

def main():

    #blahbalh

    #getting entries
    data = []

    procs = []
    for i in range(MAX_PROCESSES):
        manager = Manager()
        q = manager.list()
        p = Process(target=get_entry,args=(i,q,entries_indicies[i::MAX_PROCESSES],))
        procs += [(p,q,)]
        p.start()
    # input("Press enter when all processes finish")
    for i in procs:
        i[0].join()
        data += i[1]
    print("data", data)#debug
    print("Finished processing database!")

    #more stuff

由于join()的存在,Queue在Windows中冻结的性质仍然是个谜。所以问题仍然存在。

答案 1 :(得分:0)

正如docs所说,

警告如上所述,如果子进程已将项目放入队列中(并且未使用JoinableQueue.cancel_join_thread),则该进程将不会终止,直到所有缓冲的项目都已刷新到管道中为止。 这意味着,如果您尝试加入该进程,则可能会陷入僵局,除非您确定已放入队列中的所有项目都已消耗完。同样,如果子进程是非守护进程的,则父进程在尝试加入其所有非守护进程的子进程时可能会在退出时挂起。

请注意,使用管理器创建的队列不存在此问题。请参阅编程指南。

因此,由于multiprocessing.QueuePipe的一种,因此当您调用.join()时,队列中有一些项目,您应该先消耗{{1} }他们使空虚。然后为每个队列调用.get().close()

您也可以参考this answer