You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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.cookieslogin_resp.text来确认登录会话是否有效,确保后续下载请求能正常访问目标文件。

内容的提问来源于stack exchange,提问作者Axxi

火山引擎 最新活动