如何在Python中流式传输构建的gzip?

时间:2016-06-21 12:44:00

标签: python streaming zlib gunzip zcat

我想使用asyncio通过网络流式传输大型日志文件。我从数据库中检索数据,格式化它,使用python的zlib压缩它并通过网络传输它。

这基本上是我使用的代码:

@asyncio.coroutine
def logs(requests):
    # ...

    yield from resp.prepare(request)

    # gzip magic number and compression format
    resp.write(b'\x1f\x8b\x08\x00\x00\x00\x00\x00')
    compressor = compressobj()
    for row in rows:
        ip, uid, date, url, answer, volume = row
        NCSA_ROW = '{} {} - [{}] "GET {} HTTP/1.0" {} {}\n'
        row = NCSA_ROW.format(ip, uid, date, url, answer, volume)
        row = row.encode('utf-8')
        data = compressor.compress(row)
        resp.write(data)
    resp.write(compressor.flush())
    return resp

我检索的文件无法使用gunzip和zcat打开,引发以下错误:

gzip: out.gz: unexpected end of file

1 个答案:

答案 0 :(得分:1)

您的gzip标头错误(8个字节而不是10个字节),您使用zlib流跟随它,该流使用不同的标头和预告片。即使你有一个正确的gzip标头,如果你有一个原始的deflate流而不是gzip流,你仍然没有写一个gzip预告片。

要做到这一点,请不要尝试编写自己的gzip标头。而是请求zlib写一个完整的gzip流,它将写出正确的头,压缩数据和预告片。您可以通过向31 compressobj()提供Service值来实现此目的。