2010-03-11 8 views
30

J'ai un environnement mémoire- et limité disque où j'ai besoin de décompresser le contenu d'un fichier gzip qui m'a été envoyé en morceaux basés sur des chaînes (sur le transfert binaire xmlrpc). Cependant, en utilisant zlib.decompress() ou zlib.decompressobj()/decompress() les deux barres sur l'en-tête gzip. J'ai essayé de compenser l'en-tête de gzip (documenté here), mais je n'ai toujours pas réussi à éviter la barre. La bibliothèque gzip elle-même ne semble prendre en charge que la décompression à partir de fichiers.Python extractibles gzip morceau par morceau

L'extrait suivant donne une illustration simplifiée de ce que je voudrais faire (sauf dans la vie réelle du tampon sera rempli 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, je l'ai dit, ce vomit 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 nourrir mes données source xmlrpc-en StringIO et ensuite utiliser que comme fileobj pour gzip.GzipFile(), cependant, dans la vraie vie, je ne » t avoir de la mémoire disponible pour contenir tout le contenu du fichier en mémoire ainsi que t il décompresse les données. J'ai vraiment besoin de le traiter morceau par morceau. Le repli consisterait à changer la compression de mes données provenant de gmltp en zlib, mais puisque cela affecte d'autres sous-systèmes, je préférerais l'éviter si possible.

Des idées?

Répondre

38

gzip et zlib utilisent des en-têtes légèrement différentes.

Voir How can I decompress a gzip stream with zlib?

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

Et vous pourriez essayer de changer la taille de votre morceau à une puissance de 2 (par exemple CHUNKSIZE=1024) pour des raisons de performances possibles.

+0

qui l'a fait parfaitement. Merci. (Maintenant, pourquoi est-ce pas allusion dans la documentation de python?) – user291294

+4

zlib est juste une enveloppe autour de la version c de zlib. Ce n'est pas bien documenté du tout. Rappelez-vous, le zlib.MAX_WBITS 16 + n'est pas documenté la version c non plus, et ce n'est pas la première fois que j'ai vu une fonctionnalité zlib non documentée. – wisty

+0

doit certainement être documenté! – Ross

Questions connexes