问题描述
我正在尝试使用 Python 的 multiprocessing
库运行一些计算量很大的任务,并且我想为每个工作人员显示一个 tqdm 进度条。具体来说,我更愿意为 multiprocessing.Process
工作者或 multiprocessing.Pool
工作者提供此功能。
我知道关于这个主题的类似 StackOverflow 问题(参见例如 (1) Multiprocessing : use tqdm to display a progress bar,(2) Show the progress of a Python multiprocessing pool imap_unordered call?,(3) tqdm progress bar and multiprocessing )但他们似乎都对显示所有工人的一个进度条。我想为每个工人显示一个进度条。
from tqdm import notebook
import time
def foo2(id):
total = 100
with notebook.tqdm(total=total,position=id) as pbar:
for _ in range(0,total,5):
pbar.update(5)
time.sleep(0.1)
当我按顺序尝试时,我得到了预期的结果:5 个进度条一个接一个地填满。
但是,当我尝试使用 multiprocessing
执行此操作时,我获得了所需的加速,但没有显示进度条。无论我使用 Pool
工人还是 Process
工人,都是如此。这是我的示例代码:
%%time
from multiprocessing import Pool
pool = Pool(5)
pool.map(foo2,range(5))
pool.close()
pool.join()
根据此处的评论 (https://github.com/tqdm/tqdm/issues/407#issuecomment-322932800),我尝试使用多个 ThreadPool
工人,奇怪的是, 能够生成进度条。但是,对于我的情况,我更愿意使用带有进度条的 Pool
或 Process
工人。
%%time
from multiprocessing.pool import ThreadPool
pool = ThreadPool(5)
pool.map(foo2,range(5))
pool.close()
pool.join()
ThreadPool - progress bars show!
希望有人能帮我解决这个问题。我已经尝试了我能想到的一切。作为参考,我使用的是 Python 3.7.7
和 tqdm 4.57.0
。
解决方法
在主要 github 页面上搜索 tqdm
的问题帖子,我发现了一个对我有用的黑客,但它绝对感觉像是“黑客”而不是真正的问题修复:https://github.com/tqdm/tqdm/issues/485#issuecomment-473338308
新的(工作)代码如下所示:
from tqdm import notebook
import time
def foo2(id):
total = 100
print(' ',end='',flush=True)
for _ in notebook.tqdm(range(0,total,5)):
time.sleep(0.1)
加上
%%time
pool = Pool(5)
#pool.map(foo2,range(5)) # this also works fine with the new hack
for i in range(5):
pool.apply_async(foo2,args=(i,))
pool.close()
pool.join()