使用请求在python中下载大文件

新手上路,请多包涵

Requests 是一个非常好的库。我想用它来下载大文件(> 1GB)。问题是不可能将整个文件保存在内存中。我需要分块阅读。这是以下代码的问题:

 import requests

def DownloadFile(url)
    local_filename = url.split('/')[-1]
    r = requests.get(url)
    f = open(local_filename, 'wb')
    for chunk in r.iter_content(chunk_size=512 * 1024):
        if chunk: # filter out keep-alive new chunks
            f.write(chunk)
    f.close()
    return

由于某种原因,它不能以这种方式工作;在将响应保存到文件之前,它仍会将响应加载到内存中。

原文由 Roman Podlinov 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 764
2 个回答

使用以下流式代码,无论下载文件的大小如何,Python 内存使用都会受到限制:

 def download_file(url):
    local_filename = url.split('/')[-1]
    # NOTE the stream=True parameter below
    with requests.get(url, stream=True) as r:
        r.raise_for_status()
        with open(local_filename, 'wb') as f:
            for chunk in r.iter_content(chunk_size=8192):
                # If you have chunk encoded response uncomment if
                # and set chunk_size parameter to None.
                #if chunk:
                f.write(chunk)
    return local_filename

请注意,使用 iter_content 返回的字节数不完全是 chunk_size ;预计它是一个通常更大的随机数,并且预计在每次迭代中都会有所不同。

请参阅 body-content-workflowResponse.iter_content 以获取更多参考。

原文由 Roman Podlinov 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果使用 Response.rawshutil.copyfileobj() 会容易得多:

 import requests
import shutil

def download_file(url):
    local_filename = url.split('/')[-1]
    with requests.get(url, stream=True) as r:
        with open(local_filename, 'wb') as f:
            shutil.copyfileobj(r.raw, f)

    return local_filename

这样就可以在不使用过多内存的情况下将文件流式传输到磁盘,而且代码也很简单。

注意:根据 文档Response.raw 不会 解码 gzipdeflate 传输编码,因此您需要手动执行此操作。

原文由 John Zwinck 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题