Python多进程中实现tqdm进度条无重复原地更新
解决多进程下tqdm进度条重复/混乱的问题
我太懂这种烦躁感了——跑几个小时的多进程任务,结果进度条挤成一团根本没法看。这个问题主要是多进程输出没同步,再加上进度条的更新逻辑和位置控制没做对,咱们直接来改好它:
问题根源拆解
- update用法错误:你原来的
progressbar.update(i)是错的——tqdm的update()接收的是进度增量,不是当前进度值,每次完成一个任务应该传1而非i。 - 无输出锁机制:多进程同时往stdout写内容,没有同步锁的话,进度条的输出会互相覆盖、错位。
- 位置控制缺保障:虽然指定了
position=n_process,但没锁的话还是会出现进度条乱跑的情况。
修改后的可运行代码
from datetime import date, timedelta from multiprocessing import Pool, Lock from tqdm import tqdm def some_func(date1): # 模拟耗时任务 for i in range(1000000): pass def load_data(args): date1, n_process, lock = args dLength = 100 # 用lock同步多进程输出,position固定进度条的行位置 with tqdm(total=dLength, position=n_process, lock=lock) as progressbar: for _ in range(dLength): some_func(date1) # 每完成一个任务,进度条前进1步 progressbar.update(1) if __name__ == '__main__': d1 = date(2018, 5, 22) d2 = date(2018, 5, 26) delta = d2 - d1 dates_range = [d1 + timedelta(i) for i in range(delta.days + 1)] n_processes = 5 # 创建全局锁,传给每个进程同步输出 lock = Lock() # 打包任务参数:日期、进程位置、锁 task_args = [(dates_range[i], i, lock) for i in range(min(n_processes, len(dates_range)))] with Pool(n_processes) as p: p.map(load_data, task_args)
核心改进说明
- 全局输出锁:创建
Lock对象并传入每个进程,tqdm的lock参数会用它来控制输出顺序,避免多个进度条同时写入导致混乱。 - 正确的进度更新:每次调用
progressbar.update(1),对应完成一个子任务,进度条稳步前进。 - 固定行位置:
position=n_process让每个进程的进度条固定在专属行,更新时只会修改本行内容,不会跑到其他行干扰。 - 参数简化:把日期、位置、锁打包成元组用
map传递,比starmap更简洁直观。
这样改完之后,每个进程的进度条会在独立的行里平稳更新,你能清晰追踪每个任务的执行进度啦!
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

