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

Python读取gzip文件报zlib.error: Error -3解压错误解决方案

问题根因

报错不是单条数据损坏导致的,核心问题是写入逻辑不符合gzip格式规范:

  • 每次调用gzip.open(..., 'a')追加写入时,Python的gzip模块会在当前文件末尾写入一个全新的独立gzip压缩流(包含独立流头、压缩数据、校验尾),最终生成的文件是多个独立gzip块的直接拼接产物
  • 常规gzip读取逻辑默认只识别第一个完整压缩流,读到后续拼接流的位置时,压缩上下文不匹配,就会抛出zlib.error: Error -3 while decompressing data: invalid distance too far back错误。
方案1:无需修复文件,直接读取所有有效数据

用zlib增量解压逻辑,遇到解压错误时自动重置解压上下文,跳过错误字节寻找下一个有效gzip流,同时自动跳过JSON解析失败的行,代码如下:

import zlib
import json

def read_multi_stream_gzip(file_path, chunk_size=1024*1024):
    valid_lines = []
    # 初始化适配gzip格式的增量解压对象
    decompressor = zlib.decompressobj(16 + zlib.MAX_WBITS)
    buffer = b""
    
    with open(file_path, "rb") as f:
        while True:
            chunk = f.read(chunk_size)
            if not chunk:
                break
            try:
                decompressed = decompressor.decompress(chunk)
                buffer += decompressed
                # 拆分已解压的完整行
                while b"\n" in buffer:
                    line_raw, buffer = buffer.split(b"\n", 1)
                    line_raw = line_raw.strip()
                    if not line_raw:
                        continue
                    try:
                        valid_lines.append(json.loads(line_raw.decode("utf-8")))
                    except json.JSONDecodeError:
                        continue
            except zlib.error:
                # 遇到流错误,重置解压对象,回退1字节继续扫描下一个有效流
                decompressor = zlib.decompressobj(16 + zlib.MAX_WBITS)
                f.seek(-(len(chunk) - 1), 1)
                buffer = b""
    # 处理缓冲区最后剩余的内容
    if buffer.strip():
        try:
            valid_lines.append(json.loads(buffer.decode("utf-8")))
        except:
            pass
    return valid_lines

# 调用示例
data = read_multi_stream_gzip("tweets.gz")
方案2:修复现有文件+修正后续写入逻辑

修复现有文件

系统自带的gzip命令原生支持解压多个拼接的gzip流,直接用命令行转储一次就能生成规范的单流gzip文件,成功率远高于自定义脚本:

gzip -dc tweets.gz | gzip -c > tweets_fixed.gz

修复后的tweets_fixed.gz可以直接用原有读取代码正常打开遍历。

修正后续写入逻辑

不要再每次写入都重新以追加模式打开gzip文件,两种正确写法二选一:

  • 流式持续写入场景:初始化时打开一次文件句柄,所有数据写完再关闭
    # 初始化阶段打开文件,指定文本模式自动处理编码
    fout = gzip.open(output_path + out_fn, 'wt', encoding='utf-8')
    
    # 每次新数据到达时直接写入,无需重复open
    json_line = json.dumps(json.loads(data)) + "\n"
    fout.write(json_line)
    fout.flush()  # 按需调用,避免内容滞留缓冲区
    
    # 所有数据写入完成后关闭句柄
    fout.close()
    
  • 必须跨批次/跨进程追加场景:放弃gzip追加模式,每次追加前先解压现有内容,合并新数据后重新压缩(大文件场景效率较低)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:27:25