You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么zlib.decompressobj解压成功但zlib.decompress会失败?

zlib.decompressobj与zlib.decompress解压行为差异说明

问题复现

你提供的测试代码如下:

import zlib

data = b'x\x9c4\xc9A\x0e\x820\x10\x05\xd0\xbb\xfcuK\x8a\xe8f\xaeB\t\x19`\x82MJ!\xed\xa81M\xef\xae\x1bw/y\x15\nJ\xcf\x18\r\xca\x1f\xc7\t\xea\x9c\xc1\n\xaax\x08g\x9d\x85u\nI%\xbf8\x82n\xdd\xf5\xfe\xfbI3/\x02\x1a0xl\xac\xf2\xe6\x8f=\xf3jw\x0e\xc9\xf6E7\x0fS=\xf6\xb0\xe4\xa3x\x90\xbb\xb86bl\xed\x0b\x00\x00\xff\xff'

result = zlib.decompressobj().decompress(data)
print(result)

result2 = zlib.decompress(data)
print(result2)

运行后decompressobj成功返回解压后的JSON片段,decompress抛出zlib.error: Error -5 while decompressing data: incomplete or truncated stream错误。

根本原因

两个接口的设计定位完全不同:

  • zlib.decompress是一次性完整解压接口,要求输入的压缩数据必须是完整的zlib格式数据流,包含标准头部、压缩内容、尾部Adler32校验和,只要检测到数据流不完整就会直接抛出异常,不会返回已解压的部分内容。
  • zlib.decompressobj是流式解压接口,设计用来应对压缩数据分片到达的场景,调用decompress方法时会尽可能解析当前输入块中所有可识别的压缩内容,哪怕数据流没有结束、缺少尾部校验,也会返回已经解压成功的内容,只有遇到格式非法的内容才会抛出异常。

你提供的测试用压缩数据恰好是截断的,缺少尾部4字节的Adler32校验和,因此触发了两个接口的行为差异。

修复方案

如果需要用zlib.decompress处理截断的压缩流,可以从捕获的异常中提取已解压的内容:

import zlib

data = b'x\x9c4\xc9A\x0e\x820\x10\x05\xd0\xbb\xfcuK\x8a\xe8f\xaeB\t\x19`\x82MJ!\xed\xa81M\xef\xae\x1bw/y\x15\nJ\xcf\x18\r\xca\x1f\xc7\t\xea\x9c\xc1\n\xaax\x08g\x9d\x85u\nI%\xbf8\x82n\xdd\xf5\xfe\xfbI3/\x02\x1a0xl\xac\xf2\xe6\x8f=\xf3jw\x0e\xc9\xf6E7\x0fS=\xf6\xb0\xe4\xa3x\x90\xbb\xb86bl\xed\x0b\x00\x00\xff\xff'

try:
    result2 = zlib.decompress(data)
except zlib.error as e:
    # 截断错误的异常对象第二个参数就是已解压完成的内容
    if e.args[0] == -5:
        result2 = e.args[1]
print(result2)

运行后得到的结果和decompressobj返回的内容完全一致。

内容的提问来源于stack exchange,提问作者Kvothe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 22:15:00