并行进程覆盖进度条(tqdm)

时间:2019-06-20 09:53:35

标签: python-3.x concurrency parallel-processing tqdm

我正在用Python 3.7编写一个脚本,该脚本使用multiprocessing.Process(每个内核一个任务)启动多个并行任务。为了跟踪每个过程的进度,我使用了实现进度条的库tqdm。我的代码如下所示:

with tqdm(total=iterator_size) as progress_bar:
     for row in tqdm(batch):
         process_batch(batch)
         progress_bar.update(1)

确实确实会更新进度条,但是由于有多个进程运行上面的代码,因此每个进程都会覆盖控制台上的进度条,如下面的屏幕快照所示。

enter image description here

完成后,控制台会正确显示完成的进度条:

enter image description here

我的目标是更新进度条,而不会彼此覆盖。有什么办法可以做到这一点?

一种可能的解决方案是仅在需要花费最长时间的过程上显示进度条(我事先知道哪个是哪个),但是最好的情况是为每个过程根据第二个更新一个图片。

所有解决方案的在线地址均为multiprocess.Pool,但我不打算更改自己的体系结构,因为我可以充分利用multiprocess.Process

2 个答案:

答案 0 :(得分:1)

要进行更新而不覆盖,您需要使用tqdm的position参数,您可以找到here。这里,position=0代表最外面的条,position=1代表下一个的条,依此类推,其中0和1是在打印进度条之前要跳过的行数,即0表示0行之后的进度条,以及1表示1行之后。由于position需要跳过的行数,因此需要使用multiprocessing.current_process

可以获取的进程索引

(注意:请勿输入pid号,因为它将在打印前跳过那么多行)

from multiprocessing import current_process

""" Your code Here
Here, the current_process() is the process object
current_process().name gives the name of the process
current_process()._identity gives a tuple of the number of process
"""

current = current_process()
with tqdm(total=iterator_size) as progress_bar:
    for row in tqdm(batch, desc=str(current.name),
              position=current._identity[0] - 1)):
        process_batch(batch)
        progress_bar.update(1)

答案 1 :(得分:1)

您可以使用 update

在并行循环中更新进度条
def func(x, pbar):
    for el in batch:
        do_something_with_el(el)
        pbar.update(1)

with tqdm(total=len(your_list)) as pbar:
    batches = np.array_split(your_list, how_many_batches)
    Parallel(n_jobs=-1, prefer='threads')(delayed(func)(batch, pbar)
        for batch in batches)    

这不会产生很多进度条