Python 按块解压 gzip

42 投票
2 回答
35766 浏览
提问于 2025-04-15 20:17

我有一个内存和磁盘都有限的环境,需要解压缩通过字符串块发送给我的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 

理论上,我可以把xmlrpc传来的数据放进一个StringIO中,然后用它作为gzip.GzipFile()的文件对象,但实际上,我没有足够的内存来同时存放整个文件内容和解压后的数据。我确实需要逐块处理。

一个备选方案是把xmlrpc传来的数据的压缩格式从gzip改成普通的zlib,但这会影响其他子系统,所以如果可以的话,我希望避免这样做。

有没有什么好的建议?

2 个回答

4

我这里有一个更详细的回答:https://stackoverflow.com/a/22310760/1733117

d = zlib.decompressobj(zlib.MAX_WBITS|32)

根据文档,这个会自动识别头部信息(zlib 或 gzip)

57

gzip和zlib使用的头部信息稍微有点不同。

可以参考这个链接:如何用zlib解压gzip流?

你可以试试这个代码:d = zlib.decompressobj(16+zlib.MAX_WBITS)

另外,你也可以尝试把你的数据块大小改成2的幂次方,比如说CHUNKSIZE=1024,这样可能会提高性能。

撰写回答