2010-03-11 13 views
30

Tengo un entorno limitado en memoria y disco donde necesito descomprimir el contenido de un archivo gzip enviado a mí en fragmentos basados ​​en cadenas (a través de la transferencia binaria xmlrpc). Sin embargo, usando zlib.decompress() o zlib.decompressobj()/descompress() ambos barf sobre el encabezado gzip. Intenté compensar el encabezado gzip (documentado here), pero todavía no he logrado evitar el barf. La biblioteca gzip en sí misma solo parece ser compatible con la descompresión de archivos.Descompresión de Python gzip trozo por trozo

El siguiente fragmento da una ilustración simplificada de lo que me gustaría hacer (excepto en la vida real el buffer se llena desde xmlrpc, en lugar de leer desde un archivo local):

#! /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() 

Por desgracia, como dije, esto barfs con:

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 

en teoría, podría alimentar a mis datos xmlrpc de fuentes en un StringIO y luego usar eso como una fileobj para gzip.GzipFile(), sin embargo, en la vida real, I don' t tiene memoria disponible para mantener todo el contenido del archivo en la memoria y t él descomprimió datos. Realmente necesito procesarlo pedazo por pedazo.

El inconveniente sería cambiar la compresión de mis datos xmlrpc desde gzip a plain zlib, pero como eso afecta a otros subsistemas, preferiría evitarlo si es posible.

¿Alguna idea?

Respuesta

38

gzip y zlib utilizan encabezados ligeramente diferentes.

Ver How can I decompress a gzip stream with zlib?

Trate d = zlib.decompressobj(16+zlib.MAX_WBITS).

Y puede intentar cambiar el tamaño de su fragmento a una potencia de 2 (por ejemplo, CHUNKSIZE=1024) por posibles motivos de rendimiento.

+0

Eso lo hizo perfectamente. Gracias. (Ahora, ¿por qué esta insinuación no está en los documentos de python?) – user291294

+4

zlib es solo un envoltorio alrededor de la versión c de zlib. No está bien documentado en absoluto. Eso sí, el 16 + zlib.MAX_WBITS tampoco está documentado en la versión c, y no es la primera vez que veo una función zlib no documentada. – wisty

+0

definitivamente necesita ser documentado! – Ross

Cuestiones relacionadas