多处理pool.map不按顺序处理列表

时间:2016-11-18 18:53:11

标签: python multiprocessing python-multiprocessing

我有这个脚本来并行处理一些网址:

import multiprocessing
import time

list_of_urls = []

for i in range(1,1000):
    list_of_urls.append('http://example.com/page=' + str(i))

def process_url(url):
    page_processed = url.split('=')[1]
    print 'Processing page %s'% page_processed
    time.sleep(5)

pool = multiprocessing.Pool(processes=4)
pool.map(process_url, list_of_urls)

列表是有序的,但是当我运行它时,脚本不会按顺序从列表中选择URL:

Processing page 1
Processing page 64
Processing page 127
Processing page 190
Processing page 65
Processing page 2
Processing page 128
Processing page 191

相反,我希望它首先处理第1,2,3,4页,然后继续按照列表中的顺序。有没有选择这样做?

2 个答案:

答案 0 :(得分:3)

如果你没有传递参数chunksize map将使用这个算法计算块:

chunksize, extra = divmod(len(iterable), len(self._pool) * 4)
if extra:
   chunksize += 1

它将你的iterable切入task_batches并在sperate进程中运行它。这就是为什么它不合适。解决方案是将chunk equil声明为1。

import multiprocessing
import time

list_test = range(10)

def proces(task):
    print "task:", task
    time.sleep(1)

pool = multiprocessing.Pool(processes=3)
pool.map(proces, list_test, chunksize=1)

task: 0
task: 1
task: 2
task: 3
task: 4
task: 5
task: 6
task: 7
task: 8
task: 9

答案 1 :(得分:0)

多处理是一种异步操作,这意味着它按照定义是非顺序的。线程(或在python的case进程中)从列表中提取URL,并且无法保证哪个进程将首先完成。因此url 1可能会在url 64之前开始处理,但由于网络I / O中的随机性,例如,url 64可能首先完成。

首先,问问自己是否真的需要按顺序执行这些操作。如果答案是肯定的,那么最好的办法是执行阻塞步骤 - 强制所有并行计算首先完成,然后对完成的结果进行排序。

因此,如果您的网址列表非常大,并且您想要一些订单元素但仍然利用并行化,则可以对列表进行分块,然后通过上面的并行逻辑顺序运行每个块。