Python中如何实现多线程下载时同时显示多个进度条?
希望能分享点相关的代码示例或资料
开始时想用 tqdm 来着,但总有显示串行等奇怪的 bug.
相关代码大致如下:
from tqdm import tqdm
from multiprocessing.dummy import Pool
def dw(url):
r = requests.get(url, stream=True)
size = int(r.headers[‘Content-Length’])
progress = tqdm(total=size)
with open(‘file’, ‘wb’) as f:
for chunk in r.iter_content(1024):
progress.update(len(chunck))
f.write(chunck)
progress.close()
pool = Pool(5)
for i in urls:
pool.apply_async(dw,args=(i))
pool.close()
pool.join()
Python中如何实现多线程下载时同时显示多个进度条?
如果用多线程下载一个文件,那么下载的只是同一个文件的不同区域,分开显示意义不大。
核心方案: 用 threading 起多个下载线程,每个线程独立更新自己的进度条。tqdm 库是显示多个进度条最直接的工具,它线程安全,能自动处理并发更新。
直接上代码:
import threading
import requests
from tqdm import tqdm
import os
def download_file(url, save_path, desc):
"""
带进度条的下载函数
"""
response = requests.get(url, stream=True)
total_size = int(response.headers.get('content-length', 0))
with open(save_path, 'wb') as file, tqdm(
desc=desc,
total=total_size,
unit='B',
unit_scale=True,
unit_divisor=1024,
# 确保每个进度条有独立的位置,避免刷新冲突
position=None if total_size > 0 else None, # tqdm自动处理
leave=True # 下载完成后保留进度条
) as bar:
for data in response.iter_content(chunk_size=1024):
size = file.write(data)
bar.update(size)
def main():
# 示例:同时下载三个文件
download_list = [
("https://example.com/file1.zip", "file1.zip", "文件1"),
("https://example.com/file2.zip", "file2.zip", "文件2"),
("https://example.com/file3.zip", "file3.zip", "文件3")
]
threads = []
for url, save_path, desc in download_list:
# 跳过已存在的文件(可选)
if os.path.exists(save_path):
print(f"{desc} 已存在,跳过")
continue
thread = threading.Thread(target=download_file, args=(url, save_path, desc))
threads.append(thread)
thread.start()
# 等待所有线程完成
for thread in threads:
thread.join()
print("所有下载完成!")
if __name__ == "__main__":
main()
关键点:
tqdm是核心:它原生支持多进度条,position参数可手动控制位置,但并发时建议让它自动管理(设为None)。- 线程安全:
tqdm的更新操作是线程安全的,多个线程同时update()不会错乱。 - 流式下载:用
requests.get(stream=True)和iter_content分块读取数据,才能实时更新进度。 - 描述清晰:通过
desc参数给每个进度条起名,方便区分。
运行效果: 你会看到三个进度条同时独立更新,类似这样:
文件1: 45%|████████████████▍ | 45.2M/100M [00:12<00:18, 3.2MB/s]
文件2: 78%|███████████████████████████▊ | 78.1M/100M [00:12<00:03, 6.1MB/s]
文件3: 23%|██████████▌ | 23.5M/100M [00:12<00:42, 1.8MB/s]
一句话建议: 用 tqdm 库,每个下载线程独立创建进度条实例即可。
可能我表达有误,同时下载多个文件.
不同线程创建自己的 tqdm 实例,传递不同的 position 参数。话说,你们用库都不看文档的吗?
试过了,还是有 bug.
多行的进度条大约需要 curses 来实现(win 下没有原生的 curses)
或者你可以使用别人弄好的,例如 blessings
我觉得你需要贴张图说明是什么样的 bug。另外,多个线程可以同时向终端 print,可能会造成混乱。加个锁试试。
上面给的 issue 的链接有我写的示例代码,需要对创建 tqdm、tqdm.update 和 tqdm.close 都要加锁。另外还有个 position 的小技巧,要从 1 开始


