Python分块解压gzip数据

42

我在一个内存和磁盘受限的环境中,需要解压以字符串形式分块发送给我的gzip文件内容(通过xmlrpc二进制传输)。然而,使用zlib.decompress()或zlib.decompressobj()/decompress()都无法处理gzip头部。我已经尝试偏移超过gzip头部(在这里有文档),但仍然无法避免错误。gzip库本身似乎只支持从文件解压缩。

以下代码片段提供了我想要实现的简化示例(实际上缓冲区将会从xmlrpc中填充,而不是从本地文件读取):

#! /usr/bin/env python

import zlib

CHUNKSIZE=1000

d = zlib.decompressobj()

f=open('23046-8.txt.gz','rb')
buffer=f.read(CHUNKSIZE)

while buffer:
  outstr = d.decompress(buffer)
  print(outstr)
  buffer=f.read(CHUNKSIZE)

outstr = d.flush()
print(outstr)

f.close()

不幸的是,正如我所说,这会出现错误:

Traceback (most recent call last):
  File "./test.py", line 13, in <module>
    outstr = d.decompress(buffer)
zlib.error: Error -3 while decompressing: incorrect header check 
理论上,我可以将XML-RPC获取的数据输入StringIO,然后将其用作gzip.GzipFile()的fileobj,但在实际生活中,我没有足够的内存来容纳整个文件内容以及解压缩后的数据。我确实需要逐块处理它。
如果必须更改xmlrpc源数据的压缩方式,则可以退回到将其从gzip更改为普通的zlib,但由于这会影响其他子系统,因此如果可能的话,我希望避免这样做。
有什么想法吗?
2个回答

57

Gzip和Zlib使用略有不同的头部。

参见如何使用zlib解压gzip流?

尝试 d = zlib.decompressobj(16+zlib.MAX_WBITS)

为了可能的性能原因,您可以尝试将块大小更改为2的幂(例如CHUNKSIZE=1024)。


做得非常好。谢谢。(现在,为什么Python文档中没有这个提示呢?) - user291294
4
zlib只是c版本zlib的包装器。它没有很好的文档说明。请注意,在c版本中,16+zlib.MAX_WBITS也没有说明,并且这并不是我第一次看到未记录的zlib功能。 - wisty
一定需要文档记录! - Ross
这对我来说一直很好,直到昨天。我这里有一个gzip文件,用命令行gzip解压缩正常,在Python中使用gzip模块也可以正常解压缩,但在zlib中提前停止。正如其他地方所指出的那样,gzip需要一个真实的文件(它可以进行seek()操作),因此我现在正在寻找替代的gzip和/或zlib实现。 - izak
谢谢!这应该在一些官方文档中注明。我为此奋斗了几个小时... - Jonathan R

4

我不想给你点踩,但是这对我来说根本不起作用。 - jds
@gwg 请尽量更加精确地描述问题,例如,具体是哪个部分出现了问题。否则,其他人将无法帮助您。感谢您的理解和配合。 - pedjjj
我并不需要帮助,因为被采纳的答案对我来说已经有效了。我发表这个意见是为了节省其他人的时间。 - jds

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