Python多进程中如何在子进程内更新共享tqdm进度条?
解决多进程中子进程更新tqdm进度条的波动问题
你的问题根源在于直接将tqdm进度条对象传递给子进程:
- 多进程间的对象是独立拷贝,子进程操作的
pbar并不是主进程的进度条实例,更新操作无效且会导致终端输出混乱。 - 主进程提前调用了
pbar.close(),导致进度条提前终止,后续子进程的输出会破坏已关闭的进度条渲染。
正确的做法是:让子进程只负责任务执行,通过队列将进度更新信号发送给主进程,由主进程统一更新进度条(因为进度条属于主进程的终端输出上下文)。
修正后的代码
import multiprocessing as mp import time from tqdm import tqdm import threading def test(task_queue, update_queue): while True: x = task_queue.get() if x is None: break for i in range(x): time.sleep(0.1) # 缩短睡眠方便测试 # 子进程只发送更新信号,不直接操作进度条 update_queue.put(1) def update_progress(update_queue, pbar, total): """主进程的线程,负责监听更新队列并更新进度条""" updated = 0 while updated < total: delta = update_queue.get() pbar.update(delta) updated += delta pbar.close() if __name__ == "__main__": total_tasks = 5050 task_queue = mp.Queue() update_queue = mp.Queue() # 用于传递进度更新信号 processes = [] # 启动子进程 for _ in range(4): p = mp.Process(target=test, args=(task_queue, update_queue)) p.start() processes.append(p) # 主进程初始化进度条,并启动监听更新的线程 pbar = tqdm(total=total_tasks) progress_thread = threading.Thread(target=update_progress, args=(update_queue, pbar, total_tasks)) progress_thread.start() # 投递任务 for idx in range(100): task_queue.put(idx) # 发送结束信号 for _ in range(4): task_queue.put(None) # 等待子进程结束 for p in processes: p.join() # 等待进度更新线程结束 progress_thread.join()
关键改进点
- 用
update_queue作为子进程和主进程的通信桥梁,子进程只负责发送需要更新的进度增量。 - 主进程启动单独线程监听更新队列,统一处理进度条更新,避免多进程直接操作终端的冲突。
- 不再传递
tqdm对象给子进程,也不提前关闭进度条,确保进度条生命周期覆盖整个任务流程。 - 移除不必要的锁:
mp.Queue本身是线程/进程安全的,无需额外加锁;进度条更新由单线程处理,也不会有竞争问题。
内容的提问来源于stack exchange,提问作者Priyatham
相关产品推荐
相关产品推荐

