使用 Python 多处理时显示 tqdm 进度条

问题描述

我正在尝试使用 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()

Pool - no progress bars

根据此处的评论 (https://github.com/tqdm/tqdm/issues/407#issuecomment-322932800),我尝试使用多个 ThreadPool 工人,奇怪的是, 能够生成进度条。但是,对于我的情况,我更愿意使用带有进度条的 PoolProcess 工人。

%%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 和 tq​​dm 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()