我如何调整下面的代码以提供关于它在脚本中的位置的反馈?我想要print(f"Processed {count} / {len(items)}")
之类的东西。
pool = mp.Pool(10)
manager = mp.Manager()
return_dict = manager.dict()
res = pool.map(first_parse, iterable=items)
pool.close()
pool.join()
data_list = list(zip(items, res))
您可以使用imap
(map
的迭代器版本(并自己打印状态。enumerate
用于在返回结果时对结果进行计数。以下设计用于在具有r
(无换行的回车(支持的终端上运行。f字符串用于格式化";完成百分比";在同一行更新的值。
import multiprocessing as mp
import time
def process(data):
time.sleep(.01)
return data * 2
if __name__ == '__main__':
with mp.Pool() as pool:
for i,res in enumerate(pool.imap(process,range(1000)),start=1):
print(f'r{i/1000:6.1%}',end='',flush=True)
但看看tqdm,了解更复杂的方法。
Mark Tolonen给出的答案是正确的,但没有抓住一个关键点:map
和imap
都按任务提交的顺序返回结果,而不是按任务完成的顺序返回。在更糟糕的情况下,假设为传递给imap
的iterable参数中的第一个项目提交的作业是最后一个完成的作业,并且您使用tqdm
作为显示您在完成任务时所处位置的可视化方法。tqdm
条将被固定在0,直到第一个任务完成。但只有在提交的所有其他任务都完成后,才会出现这种情况。所以你会看到有一段时间什么都没发生,然后突然间酒吧会在一瞬间达到100%。
要获得准确的完成进度图片,最好使用带回调函数的apply_async
(使用默认chunksize参数为1的imap_unordered
似乎可以按任务完成顺序返回结果,但文档不能保证这一点(。这可能意味着可能需要修改辅助函数以返回传递给它的原始参数,以便将结果与用于创建结果的参数绑定在一起。
现在,在您的代码中,我看不到return_dict
被传递给您的辅助函数first_pass
的位置。如果它是应该的,并且辅助函数就是在这里存储结果的,那么返回结果的顺序可能无关紧要。另一方面,我看到您使用了来自map
的返回列表,并将其压缩为items
,这表明顺序确实很重要,我将假设这一点。因此,我将把结果列表的索引传递给first_pass
,它传递回的结果应该存储在.中
import multiprocessing as mp
def first_parse(idx, item):
import time
import random
time.sleep(random.random() * 5)
... # calculate result
return idx, item ** 2 # return original idx
def my_callback(t):
global completed
idx, result = t
res[idx] = result
completed += 1
print(f"Processed {completed * 100 / result_size}%")
# required for Windows:
if __name__ == '__main__':
pool = mp.Pool(10)
#manager = mp.Manager()
# sample items:
items = range(10)
result_size = len(items)
# preallocate the res list:
res = [None] * result_size
# pass enumerate so that the result index is passed and can be returned back:
# Now first_pass argument will be a tuple:
completed = 0
for idx, item in enumerate(items):
pool.apply_async(first_parse, args=(idx, item), callback=my_callback)
pool.close()
pool.join()
data_list = list(zip(items, res))
print(data_list)
打印:
Processed 10.0%
Processed 20.0%
Processed 30.0%
Processed 40.0%
Processed 50.0%
Processed 60.0%
Processed 70.0%
Processed 80.0%
Processed 90.0%
Processed 100.0%
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64), (9, 81)]