我想使用多处理模块来加速遍历目录结构。首先,我做了一些研究,发现了这个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
我确信我在这里缺少一些简单的东西。
答案 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,))