修复 python 多处理中多个进度条 (tqdm) 的跳跃

mo_*_*blu 6 python terminal multiprocessing progress-bar tqdm

我想progresser()针对一系列输入参数 ( ) 并行化任务 ( L)。每个任务的进度应通过终端中的单独进度条进行监控。我正在使用tqdm进度条包。以下代码在我的 Mac 上最多可运行 23 个进度条(L = list(range(23))及以下),但会产生从 开始的进度条的混乱跳跃L = list(range(24))。有谁知道如何解决这个问题?

from time import sleep
import random
from tqdm import tqdm
from multiprocessing import Pool, freeze_support, RLock

L = list(range(24)) # works until 23, breaks starting at 24

def progresser(n):
    text = f'#{n}'

    sampling_counts = 10
    with tqdm(total=sampling_counts, desc=text, position=n+1) as pbar:
        for i in range(sampling_counts):
            sleep(random.uniform(0, 1))
            pbar.update(1)

if __name__ == '__main__':
    freeze_support()

    p = Pool(processes=None,
                initargs=(RLock(),), initializer=tqdm.set_lock
                )
    p.map(progresser, L)
    print('\n' * (len(L) + 1))
Run Code Online (Sandbox Code Playgroud)

作为一般情况下的示例,我提供了L = list(range(16))下面的屏幕截图。

多处理进度条

版本:python==3.7.3,tqdm==4.32.1

Sha*_*n L 5

当我将大小设置为 30 时,我没有任何跳跃。也许您有更多的处理器并且可以运行更多的工作线程。

然而,如果 n 变大,由于块大小的性质,您将开始看到跳跃。

p.map会将您的输入分割成块大小并给每个进程一个块。因此,随着n变大,你的 chunksize 也会变大,你的 ....... 是的position(pos=n+1)!

注意:虽然map保留了返回结果的顺序。其计算的顺序是任意的。

随着n规模的扩大,我建议使用处理器 ID 作为查看每个进程的进度的位置。

from time import sleep
import random
from tqdm import tqdm
from multiprocessing import Pool, freeze_support, RLock
from multiprocessing import current_process


def progresser(n):
    text = f'#{n}'
    sampling_counts = 10
    current = current_process()
    pos = current._identity[0]-1

    with tqdm(total=sampling_counts, desc=text, position=pos) as pbar:
        for i in range(sampling_counts):
            sleep(random.uniform(0, 1))
            pbar.update(1)

if __name__ == '__main__':
    freeze_support()
    L = list(range(30)) # works until 23, breaks starting at 24
    # p = Pool(processes=None,
    #         initargs=(RLock(),), initializer=tqdm.set_lock
    #         )
    with Pool(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),)) as p: 
        p.map(progresser, L)
        print('\n' * (len(L) + 1))
Run Code Online (Sandbox Code Playgroud)