Python décompression gzip morceau par morceau
j'ai un environnement limité en mémoire et disque où je dois décompresser le contenu d'un fichier gzip qui m'est envoyé en morceaux basés sur des chaînes de caractères (sur xmlrpc binaire de transfert). Cependant, en utilisant le zlib.décompress () ou zlib.décompressobj () / décompress () les deux barf au-dessus de l'en-tête gzip. J'ai essayé de compenser au-delà de l'en-tête gzip (documenté ici ), mais je n'ai toujours pas réussi à éviter le barf. La bibliothèque gzip elle-même ne semble prendre en charge que la décompression à partir des fichiers.
l'extrait suivant donne une illustration simplifiée de ce que je voudrais faire (sauf dans la vie réelle, le tampon sera rempli à partir de xmlrpc, plutôt que de lire à partir d'un fichier 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()
malheureusement, comme je l'ai dit, ce BARF avec:
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
théoriquement, je pourrais alimenter mes données xmlrpc dans un StringIO et ensuite l'utiliser comme un fileobj pour gzip.GzipFile(), cependant, dans la vraie vie, je n'ai pas de mémoire disponible pour conserver tout le contenu du fichier en mémoire ainsi que les données décompressées. J'ai vraiment besoin de traiter morceau par morceau.
la solution de rechange serait de changer la compression de mes données provenant de xmlrpc de gzip à plain zlib, mais puisque cela affecte d'autres sous-systèmes, Je préférerais l'éviter si possible.
des idées?
2 réponses
gzip et zlib utilisent des en-têtes légèrement différents.
Voir Comment décompresser un gzip flux avec zlib?
Essayer d = zlib.decompressobj(16+zlib.MAX_WBITS)
.
et vous pourriez essayer de changer la taille de votre morceau à une puissance de 2 (dites CHUNKSIZE=1024
) pour des raisons de performance possibles.
j'ai une réponse plus détaillée ici: https://stackoverflow.com/a/22310760/1733117
d = zlib.decompressobj(zlib.MAX_WBITS|32)
par documentation ceci détecte automatiquement l'en-tête (zlib ou gzip) .