代码之家  ›  专栏  ›  技术社区  ›  Anon

Python-使用请求将文件直接下载到内存

  •  33
  • Anon  · 技术社区  · 11 年前

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

    这是我通常从网上下载内容并将其映射到内存的方式:

    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?
    
    3 回复  |  直到 11 年前
        1
  •  49
  •   jfs    9 年前

    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()})
    

    你不能通过 未加工的 ZipFile() 直接因为前者是不可查找的文件。

    我想看看是否可以避免编写文件删除行代码

    tempfile 可以自动删除文件 f = tempfile.SpooledTemporaryFile(); f.write(u.content) 直到 .fileno() 方法(如果某些api需要实际文件)或 maxsize 达到;数据保存在存储器中。即使数据写入磁盘;文件一关闭就被删除。

        2
  •  12
  •   Anon    11 年前

    这就是我最后做的。

    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
  •  11
  •   poke    11 年前

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