【问题标题】:Python - Download File Using Requests, Directly to MemoryPython - 使用请求下载文件,直接到内存
【发布时间】:2014-03-12 01:36:22
【问题描述】:

目标是从 Internet 下载文件,并从中创建文件对象或类似文件的对象,而无需接触硬盘驱动器。这只是为了我的知识,想知道它是否可能或实用,特别是因为我想看看我是否可以避免编写文件删除行。

这就是我通常会从网络上下载东西并将其映射到内存的方式:

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?

【问题讨论】:

标签: python python-requests mmap


【解决方案1】:

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),在不接触磁盘的情况下得到一个类似文件的对象:

#!/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;数据保存在内存中。即使数据写入磁盘;文件一关闭就被删除。

【讨论】:

    【解决方案2】:

    这就是我最终要做的。

    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)
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 如何获取 u.content,并创建一个类似对象的文件(mmap 的作用),而不将其写入磁盘?
      猜你喜欢
      • 1970-01-01
      • 2013-04-05
      • 2021-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 2013-05-17
      相关资源
      最近更新 更多