Python Requests 下载文件时进度条瞬间完成问题求助
解决requests流式下载CSV时tqdm进度条瞬间跳满的问题
嘿,我明白你遇到的困扰了——文件能正常下载,但进度条直接跳到100%,完全没有实时更新的过程。咱们来看看问题出在哪,然后一步步解决它。
问题根源
你当前代码里的total = len(resp.content)是罪魁祸首!当你调用resp.content时,requests会一次性把整个文件下载到内存里,这直接绕过了stream=True的流式下载机制。等你开始用iter_content迭代的时候,文件其实已经全在内存里了,进度条自然会瞬间走完。
修复方案
我们需要从响应头里获取文件的总大小,而不是提前加载整个文件内容。同时要确保stream=True真正发挥作用,让内容分块下载。
以下是修改后的完整代码:
from datetime import datetime import requests from tqdm import tqdm def download(): resp = s.get(url, stream=True) # 从响应头获取文件总大小,转成整数;如果服务器没返回则设为0 total = int(resp.headers.get('Content-Length', 0)) # 构造保存的文件名,用f-string更简洁 save_path = f'C:/Users/axxi/Documents/{datetime.today().strftime("%Y-%m-%d")}.csv' with open(save_path, 'wb') as file, tqdm( total=total, unit='iB', unit_scale=True, unit_divisor=1024, desc=save_path.split('/')[-1] # 增加文件名作为进度条描述,更直观 ) as bar: for data in resp.iter_content(chunk_size=1024): size = file.write(data) bar.update(size) # 处理服务器未返回文件大小的情况 if total == 0: print("提示:服务器未返回文件大小,进度条无法显示准确总进度,但仍会实时更新已下载量") url = 'random url.com' values = {'username': 'username', 'password': 'password'} s = requests.Session() # 登录请求不需要stream=True,除非返回内容特别大 login_resp = s.post(url, data=values) # 检查登录是否成功,避免无效下载 if login_resp.status_code == 200: print("登录成功,开始下载文件...") download() else: print(f"登录失败,状态码:{login_resp.status_code}")
关键改动说明
- 正确获取总大小:通过
resp.headers.get('Content-Length', 0)从HTTP响应头获取文件总大小,避免提前加载整个文件破坏流式下载。 - 保留流式下载逻辑:不再调用
resp.content,确保iter_content分块读取内容,进度条能实时更新。 - 增加登录状态验证:提前确认登录请求是否成功,避免登录失败后做无用功。
- 优化进度条体验:添加
desc参数显示文件名,让进度条更直观。 - 兼容异常场景:当服务器没有返回
Content-Length时,给出友好提示,避免程序报错。
额外注意事项
- 有些服务器可能不会返回
Content-Length(比如动态生成的文件),这种情况进度条会显示为无上限的状态,但依然会实时更新已下载的字节数。 - 可以通过打印
login_resp.cookies或login_resp.text来确认登录会话是否有效,确保后续下载请求能正常访问目标文件。
内容的提问来源于stack exchange,提问作者Axxi




