使用gzip编码(Python 3.4)分块下载大文件

3

如果我请求一个文件并指定gzip编码,我该如何处理?

通常当我有一个大文件时,我会按照以下方式处理:

while True:
   chunk = resp.read(CHUNK)
   if not chunk: break
   writer.write(chunk)
   writer.flush()

其中CHUNK是以字节为单位的一些大小,writer是一个open()对象,resp是由urllib请求生成的请求响应。

因此,当响应头包含“gzip”作为返回编码时,大多数情况下很简单,我会执行以下操作:

decomp = zlib.decompressobj(16+zlib.MAX_WBITS)
data = decomp.decompress(resp.read())
writer.write(data)
writer.flush()

或者这个:
f = gzip.GzipFile(fileobj=buf)
writer.write(f.read())

其中buf是一个BytesIO()对象。

然而,如果我尝试解压gzip响应,就会遇到问题:

while True:
   chunk = resp.read(CHUNK)
   if not chunk: break
   decomp = zlib.decompressobj(16+zlib.MAX_WBITS)
   data = decomp.decompress(chunk)
   writer.write(data)
   writer.flush()

我是否可以在数据以小块形式下载时解压gzip数据?或者我需要将整个文件写入磁盘、解压缩它,然后将其移动到最终文件名称?使用32位Python的问题之一是,我可能会遇到内存错误。

谢谢

1个回答

3

我认为我找到了一个解决方案,想要分享一下。

def _chunk(response, size=4096):
     """ downloads a web response in pieces """
    method = response.headers.get("content-encoding")
    if method == "gzip":
        d = zlib.decompressobj(16+zlib.MAX_WBITS)
        b = response.read(size)
        while b:
            data = d.decompress(b)
            yield data
            b = response.read(size)
            del data
    else:
        while True:
            chunk = response.read(size)
            if not chunk: break
            yield chunk

如果有更好的解决方案,请添加进来。基本上我的错误是在创建zlib.decompressobj()的位置错了。 这似乎在Python 2和3中都有效,所以这是一个加分项。

del data 有什么作用? - Janosh

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