Python descomprimiendo gzip fragmento por fragmento


Tengo un entorno limitado a la memoria y al disco en el que necesito descomprimir el contenido de un archivo gzip enviado a mí en trozos basados en cadenas (sobre transferencia binaria xmlrpc). Sin embargo, usando el zlib.descomprimir() o zlib.decompressobj () / decompress () ambos barf sobre la cabecera gzip. He intentado compensar más allá del encabezado gzip (documentado aquí), pero todavía no he logrado evitar el barf. La biblioteca gzip en sí solo parece soportar la descompresión desde archivos.

Lo siguiente snippet da una ilustración simplificada de lo que me gustaría hacer (excepto que en la vida real el búfer se llenará 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()

Desafortunadamente, como he dicho, este vomita 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 

Teóricamente, podría alimentar mis datos de origen xmlrpc en un StringIO y luego usarlo como fileobj para gzip.GzipFile (), sin embargo, en la vida real, no tengo memoria disponible para mantener todo el contenido del archivo en memoria, así como los datos descomprimidos. Me realmente necesito procesarlo fragmento por fragmento.

La alternativa sería cambiar la compresión de mis datos de origen xmlrpc de gzip a zlib simple, pero como eso afecta a otros subsistemas, preferiría evitarlo si es posible.

¿Alguna idea?

Author: user291294, 2010-03-11

2 answers

Gzip y zlib usan encabezados ligeramente diferentes.

Ver ¿Cómo puedo descomprimir un flujo gzip con zlib?

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

Y podrías intentar cambiar el tamaño de tu chunk a una potencia de 2 (digamos CHUNKSIZE=1024) por posibles razones de rendimiento.

 39
Author: wisty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:07

Tengo una respuesta más detallada aquí: https://stackoverflow.com/a/22310760/1733117

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

Por documentación esto detecta automáticamente el encabezado (zlib o gzip).

 3
Author: dnozay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:37