为什么在Python的requests中使用iter_content和chunk_size?

19

我为什么要使用iter_content,而且我对使用chunk_size的目的感到非常困惑,因为我尝试使用它,无论如何,文件似乎都会在下载成功后保存。

g = requests.get(url, stream=True)

with open('c:/users/andriken/desktop/tiger.jpg', 'wb') as sav:
    for chunk in g.iter_content(chunk_size=1000000):
        print (chunk)
        sav.write(chunk)

帮助我理解iter_content的用法,当你看到我使用1000000字节作为chunk_size时会发生什么,它的目的是什么以及结果是什么?

3个回答

31

这是为了避免一次性将整个响应加载到内存中(同时允许您在流式传输响应时实现某些并发,以便您可以在等待请求完成时执行工作)。

设置流式请求的目的通常是针对媒体文件的。例如,使用请求下载一个500 MB的.mp4文件,您希望流式传输响应,并将流分块写入(chunk_size大小的块),而不是一次性等待所有500MB全部加载到Python中。

如果您想要实现任何UI反馈(例如下载进度条,如“已下载<chunk_size>字节...”),则需要流式传输和分块。如果您的响应包含Content-Size头,则还可以在保存每个块时计算完成百分比。


1
你的意思是,像使用可用的数据块进行编写一样,在播放器中使用它来流式传输实际视频吗? - Andriken sonwane
嗯,是的,在你给出的例子中,sav 是一个打开的文件句柄,可以将其表示为与播放器或其他内容的打开管道。 - cowbert
是的,我现在明白了这个概念,不过你能告诉我 iter_lines 是做什么的吗? - Andriken sonwane
3
通常情况下,如果您不使用stream=True,则.get()返回的响应对象将在Response.content中保存实际的完整响应内容。但是,如果您正在使用流式传输(streaming),则.content的行为显然需要更改(它无法容纳所有数据),您需要使用iter_content方法从服务器提取后续数据块到.content并返回它。这遵循了典型的Python迭代器模式。 - cowbert
是的,我已经知道了什么时候使用stream=True,我只是有些困惑,但现在你的答案作为一个例子帮助我理解了。谢谢,上帝保佑你! - Andriken sonwane

7

根据文档chunk_size是指当stream=True时,应用程序在内存中读取的数据大小。

例如,如果响应的大小为1000,并且chunk_size设置为100,则我们将响应分成十个块。


2
在没有内容长度标头的情况下,使用HTTP1.1分块传输编码(CTE)模式或HTTP2/3数据帧时,如果需要最小延迟,则处理每个HTTP块到达可能比等待缓冲区达到特定大小更有用。
通过设置chunk_size = None可以实现这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接