如何使用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.raw
和shutil.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。 我错过了什么吗?