在Python多处理模块中使用池与队列

时间:2014-07-11 20:05:03

标签: python multithreading multiprocessing

我想使用多处理模块来加速遍历目录结构。首先,我做了一些研究,发现了这个Stack Overflow线程:

How do I run os.walk in parallel in Python?

但是,当我尝试调整线程中的代码时,我一直遇到问题。这是我编写的一个小脚本,只是测试Pool并弄清楚它是如何工作的。:

import os

from multiprocessing.pool import Pool
from multiprocessing import Process
from multiprocessing import JoinableQueue as Queue

def scan():
    print "Hi!"
    while True:
        print "Inside loop"
        directory = unsearched.get()
        print "Got directory"
        unsearched.task_done()
        print "{0}".format(directory)

if __name__ == '__main__':

    # Put those directories on the queue
    unsearched = Queue()
    top_dirs = ['a', 'b', 'c']
    for d in top_dirs:
        unsearched.put(d)
    print unsearched

    # Scan the directories
    processes = 1
    pool = Pool(processes)
    for i in range(processes):
        print "Process {0}".format(i)
        pool.apply_async(scan)

    # Block until all the tasks are done
    unsearched.join()
    print 'Done'

发生的事情是脚本进入扫描功能内部的循环内部并且只是坐在那里:

PS C:\Test> python .\multiprocessing_test.py
<multiprocessing.queues.JoinableQueue object at 0x000000000272F630>
Process 0
Hi!
Inside loop

我确信我在这里缺少一些简单的东西。

1 个答案:

答案 0 :(得分:2)

这实际上在Linux上运行正常,但确实挂在Windows上。这是因为在Windows上,if __name__ ...防护内部的所有内容都不会在子进程中执行,这当然包括定义unsearched。这意味着scan在尝试使用unsearched时会抛出异常,但该异常永远不会在父节点中使用,因此您不会在CLI中看到Traceback。相反,它只是挂起。

要在Windows和Linux上运行此功能,您可以在创建initializer时使用initargs / Pool关键字参数,以便在子级范围内生成unsearched

def initializer(q):
    global unsearched
    unsearched = q

...

然后用以下内容替换旧的Pool来电:

pool = Pool(processes, initializer=initializer, initargs=(unsearched,))