Python - 使用Requests下载文件,直接到内存中

36

目标是从互联网下载文件,并从中创建一个文件对象或类似文件的对象,而不必将其接触硬盘。这只是为了我的知识,想知道是否可能或实用,特别是因为我想看看是否可以规避编写文件删除行的代码。

这是我通常从网络上下载东西并映射到内存的方法:

import requests
import mmap

u = requests.get("http://www.pythonchallenge.com/pc/def/channel.zip")

with open("channel.zip", "wb") as f: # I want to eliminate this, as this writes to disk
    f.write(u.content)

with open("channel.zip", "r+b") as f: # and his as well, because it reads from disk
    mm = mmap.mmap(f.fileno(), 0)
    mm.seek(0)
    print mm.readline()
    mm.close() # question: if I do not include this, does this become a memory leak?

http://docs.python-requests.org/en/latest/user/quickstart/#response-content - Karl Knechtel
3个回答

50

r.raw (HTTPResponse) 已经是类似文件的对象(只需传递 stream=True):

#!/usr/bin/env python
import sys
import requests # $ pip install requests
from PIL import Image # $ pip install pillow

url = sys.argv[1]
r = requests.get(url, stream=True)
r.raw.decode_content = True # Content-Encoding
im = Image.open(r.raw) #NOTE: it requires pillow 2.8+
print(im.format, im.mode, im.size)

通常情况下,如果您有一个字节串,您可以将其包装成f = io.BytesIO(r.content),以获得一个类似文件的对象,而无需触碰磁盘:

一般来说,如果你有一个字节串,你可以使用 f = io.BytesIO(r.content) 将其封装成一个类似文件的对象,而不需要将其存到磁盘上:

#!/usr/bin/env python
import io
import zipfile
from contextlib import closing
import requests # $ pip install requests

r = requests.get("http://www.pythonchallenge.com/pc/def/channel.zip")
with closing(r), zipfile.ZipFile(io.BytesIO(r.content)) as archive:
    print({member.filename: archive.read(member) for member in archive.infolist()})

因为r.raw是一个不可寻址的文件,所以不能直接将其传递给ZipFile()

我想看看是否能够规避编写文件删除行的必要性。

tempfile可以自动删除文件f = tempfile.SpooledTemporaryFile(); f.write(u.content)。 直到调用.fileno()方法(如果某些API需要真正的文件)或达到maxsize时;数据保存在内存中。 即使数据写入磁盘,文件也会在关闭后立即被删除。


13

这就是我最终做的事情。

import zipfile 
import requests
import StringIO

u = requests.get("http://www.pythonchallenge.com/pc/def/channel.zip")
f = StringIO.StringIO() 
f.write(u.content)

def extract_zip(input_zip):
    input_zip = zipfile.ZipFile(input_zip)
    return {i: input_zip.read(i) for i in input_zip.namelist()}
extracted = extract_zip(f)

11

您的答案是u.content。内容内存中。除非将其写入文件,否则它不会存储在磁盘上。


1
你如何获取u.content,并创建一个类似于文件对象的东西(就像mmap所做的那样),而不将其写入磁盘? - Anon

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