解决Python多进程中tqdm多进度条跳转混乱问题
解决Mac上多进程tqdm进度条24任务以上混乱的问题
这个问题我之前在Mac上碰到过!根源其实和macOS的进程启动方式以及旧版tqdm的多进程兼容性有关,咱们一步步来解决:
原因分析
当任务数达到24时进度条出现混乱,主要有两个核心原因:
- 你使用的tqdm版本(4.32.1)比较老旧,在多进程+fork启动模式下,终端输出的锁机制存在兼容性bug;
- macOS默认的
multiprocessing.Pool采用fork方式创建进程,子进程会直接继承父进程的终端输出缓冲,当进程数量超过一定阈值时,就会出现输出冲突,导致进度条跳转混乱。
解决方法
方法1:升级tqdm到最新版本
旧版tqdm的多进程支持不完善,升级到最新版能直接解决很多兼容性问题,执行以下命令即可:
pip install --upgrade tqdm
方法2:改用spawn进程启动模式
避免fork带来的终端缓冲继承问题,修改Pool的创建逻辑,改用spawn上下文启动进程:
from time import sleep import random from tqdm import tqdm from multiprocessing import Pool, freeze_support, RLock, get_context L = list(range(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() # 使用spawn上下文创建进程池,避免fork的终端缓冲问题 ctx = get_context('spawn') p = Pool(processes=None, initargs=(RLock(),), initializer=tqdm.set_lock, context=ctx) p.map(progresser, L) print('\n' * (len(L) + 1))
方法3:使用tqdm官方封装的多进程工具(推荐简化版)
如果你不需要每个任务单独的进度条,只是想监控整体进度,tqdm官方提供了process_map工具,已经封装好了所有多进程的进度条处理逻辑,不用手动管理锁和进程池:
from time import sleep import random from tqdm.contrib.concurrent import process_map L = list(range(24)) def progresser(n): sampling_counts = 10 for i in range(sampling_counts): sleep(random.uniform(0, 1)) return n if __name__ == '__main__': # 调用process_map自动处理进度条 results = process_map(progresser, L, total=len(L), max_workers=None) print('\nAll tasks completed!')
额外注意事项
- 确保你的终端窗口高度足够显示所有进度条(至少需要25行以上,因为你的position参数从1到24),如果窗口尺寸太小,也会导致进度条滚动混乱;
- 如果尝试以上方法后仍有问题,可以在tqdm初始化时显式传入锁:
lock=tqdm.get_lock(),确保输出锁正确生效。
内容的提问来源于stack exchange,提问作者mo_blu
相关产品推荐
相关产品推荐

