如何使用requests.py在python下载大文件?

请求是一个非常好的库。 我想用它来下载大文件(> 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 

由于某种原因,这种方式不起作用。 它仍然将响应加载到内存中,然后将其保存到文件中。

我想清楚应该改变什么。 诀窍是在get()方法中设置stream = True

在这个python进程停止吸取内存(不论大小的下载文件保持在30kb左右)。

谢谢@danodonovan你的语法我在这里使用它:

 def download_file(url): local_filename = url.split('/')[-1] # NOTE the stream=True parameter r = requests.get(url, stream=True) with open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) #f.flush() commented by recommendation from JFSebastian return local_filename 

请参阅http://docs.python-requests.org/en/latest/user/advanced/#body-content-workflow以作进一步参考。;

如果您使用Response.rawshutil.copyfileobj()会更容易:

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

这stream文件到磁盘没有使用过多的内存,代码很简单。

你的块大小可能太大了,你有没有尝试删除 – 一次可能是1024字节? (也可以用来整理语法)

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

顺便说一下,你是如何推断出响应已经加载到内存中的?

这听起来好像python没有刷新数据文件,从其他SO问题,你可以尝试f.flush()os.fsync()强制文件写入和空闲内存;

  with open(local_filename, 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk) f.flush() os.fsync(f.fileno()) 

不是OP所要求的,但是用urllib做这件事很容易:

 from urllib.request import urlretrieve url = 'http://mirror.pnl.gov/releases/16.04.2/ubuntu-16.04.2-desktop-amd64.iso' dst = 'ubuntu-16.04.2-desktop-amd64.iso' urlretrieve(url, dst) 

或者这样,如果你想把它保存到一个临时文件:

 from urllib.request import urlopen from shutil import copyfileobj from tempfile import NamedTemporaryFile url = 'http://mirror.pnl.gov/releases/16.04.2/ubuntu-16.04.2-desktop-amd64.iso' with urlopen(url) as fsrc, NamedTemporaryFile(delete=False) as fdst: copyfileobj(fsrc, fdst) 

我看着这个过程:

 watch 'ps -p 18647 -o pid,ppid,pmem,rsz,vsz,comm,args; ls -al *.iso' 

而且我看到这个文件在增长,但是内存使用保持在17MB。 我错过了什么吗?