如何用Python实现流式下载,节省内存还带进度条!

引言

本篇文章来分享一下如何使用 Requests 下载文件并且显示进度条。

下载文件

说到下载文件,大家可能一下子就能写出以下的代码:

1
2
3
4
5
6
7
8
9
10
import requests

total = 10485
url = f'https://speed.cloudflare.com/__down?during=download&bytes={total}'
# 上面的 URL 是 cloudflare 的测试链接,可以传入想要下载的长度
res = requests.get(url)

with open('test.file', 'wb') as file:
file.write(res.content)
print('下载完成')

这样写当然没问题,但是有几个问题:

  • 文件内容都放到了内存中,并且没有下载进度
  • 如果文件很大,不光下载时间很久,而且占用很大内存无法释放,只有下载完成后才能释放
  • 没有下载进度,不知道下载是否还在进行中,不知道何时结束,不知道下载的状态

Requests 分块下载

为了解决上面的问题,我们需要用到流式传输,在使用 Requests 进行下载时,只需要将 stream 设置 True,即可开启流式传输,Requests 不会从服务器一次性将内容全部下载到本地,而是根据需求分块的从服务器获取内容,然后对内容进行处理。

举个例子:

1
2
3
4
5
6
7
8
9
10
11
import json
import requests

r = requests.get('https://httpbin.org/stream/20', stream=True)

for line in r.iter_lines():

# filter out keep-alive new lines
if line:
decoded_line = line.decode('utf-8')
print(json.loads(decoded_line))

给下载加上进度条

为了解决下载的时候没有进度像是卡住的问题,可以在下载的时候加上进度条, 并且分块进行下载,而不是将数据全部放到内存中,防止占用过大的内存。

进度条我们使用 tqdm 库,tqdm 库是一个功能强大且极具实用性的 Python 进度条工具,它能够以直观的可视化进度条形式清晰展示循环迭代、文件处理等各类任务的执行进度,极大提升程序运行状态的可视性与用户体验,广泛应用于数据处理、机器学习训练等众多领域,方便开发者与使用者实时掌握任务进展情况并有效优化程序运行流程。

先安装:

1
2
3
poetry add tqdm
# 或者
pip install tqdm

安装好后,对之前的下载代码进行优化,并且使用流式传输方法改造一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests
from tqdm import tqdm

total = 104857600 # 100M
url = f'https://speed.cloudflare.com/__down?during=download&bytes={total}'
res = requests.get(url, stream=True)
# 上面的 URL 是 cloudflare 的测试链接,可以传入想要下载的长度,如果是正常的下载文件,需要通过下面的代码来获取总长度
# file_size = int(response.headers.get("Content - Length", 0))
print(total)
with open('test.file', 'wb') as file, tqdm(
desc='test.file',
total=total,
unit='iB',
unit_scale=True,
unit_divisor=1024,
) as bar:
for data in res.iter_content(chunk_size=1024):
size = file.write(data)
bar.update(size)

下载效果:

image-20241216204542644

image-20241216204552501

image-20241216204556317

可以看到,不光有了进度条,还有了下载速度,而且还有总大小和已经下载的大小和预估时间,信息是相当全面了。

总结

上面的方法在下载大文件时非常有用,不仅可以清楚地看到下载的进度,还能避免一次性将整个文件读取到内存中,从而节省内存资源,提高程序的稳定性和效率。

本文章首发于个人博客 LLLibra146’s blog
本文作者:LLLibra146
更多文章请关注:qrcode
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!
本文链接
https://blog.d77.xyz/archives/ac6de120.html