2009-10-09 3 views
24

Я прочитал это SO post вокруг проблемы безрезультатно.Python gzip: есть ли способ распаковать строку?

Я пытаюсь распаковать файл .gz, исходящий из URL-адреса.

url_file_handle=StringIO(gz_data) 
gzip_file_handle=gzip.open(url_file_handle,"r") 
decompressed_data = gzip_file_handle.read() 
gzip_file_handle.close() 

... но я получаю TypeError: принуждать к Unicode: нужно строка или буфер, cStringIO.StringI найдено

Что происходит?

Traceback (most recent call last): 
    File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2974, in _HandleRequest 
    base_env_dict=env_dict) 
    File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 411, in Dispatch 
    base_env_dict=base_env_dict) 
    File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2243, in Dispatch 
    self._module_dict) 
    File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2161, in ExecuteCGI 
    reset_modules = exec_script(handler_path, cgi_path, hook) 
    File "/opt/google/google_appengine-1.2.5/google/appengine/tools/dev_appserver.py", line 2057, in ExecuteOrImportScript 
    exec module_code in script_module.__dict__ 
    File "/home/jldupont/workspace/jldupont/trunk/site/app/server/tasks/debian/repo_fetcher.py", line 36, in <module> 
    main() 
    File "/home/jldupont/workspace/jldupont/trunk/site/app/server/tasks/debian/repo_fetcher.py", line 30, in main 
    gziph=gzip.open(fh,'r') 
    File "/usr/lib/python2.5/gzip.py", line 49, in open 
    return GzipFile(filename, mode, compresslevel) 
    File "/usr/lib/python2.5/gzip.py", line 95, in __init__ 
    fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb') 
TypeError: coercing to Unicode: need string or buffer, cStringIO.StringI found 
+0

Пожалуйста, напишите больше из трассировки (какая строка не работает). – tonfa

+0

Будет ли использовать stringIO вместо cStringIO решить проблему? – recursive

+0

@recursive: Я уже добавил необходимые проверки наличия cStringIO и вернусь к StringIO, если нет. – jldupont

ответ

31

gzip.open является обобщающим для открытия файла, что вы хотите gzip.GzipFile, который вы можете передать fileobj

open(filename, mode='rb', compresslevel=9) 
    #Shorthand for GzipFile(filename, mode, compresslevel). 

против

class GzipFile 
    __init__(self, filename=None, mode=None, compresslevel=9, fileobj=None) 
    # At least one of fileobj and filename must be given a non-trivial value. 

так это должно работать для вас

gzip_file_handle = gzip.GzipFile(fileobj=url_file_handle) 
+0

Я смог проработать с вашим ответом: спасибо! – jldupont

34

Если данные уже находятся в строке, попробуйте Zlib, которая претендует быть полностью совместимы GZIP:

import zlib 
decompressed_data = zlib.decompress(gz_data, 16+zlib.MAX_WBITS) 

Подробнее: http://docs.python.org/library/zlib.html

+7

Это было то, что пришло ко мне в начале. Но быстро выяснилось, что он не работает: «zlib.error: Ошибка -3 при распаковке данных: неправильная проверка заголовка» – HongboZhu

+5

Добавить аргумент, чтобы вызов выглядел как 'decpressed_data = zlib.decompress (gz_data, 16 + zlib.MAX_WBITS) ', работает как прелесть для меня. Благодаря здесь http://stackoverflow.com/a/2695575/3635816 – RickardSjogren

1

Рассмотрите возможность использования gzip.GzipFile, если вам не нравится, передавая неясные аргументы zlib.decompress.

Когда вы имеете дело с urllib2.urlopen ответ, который может быть либо GZIP сжатый или несжатый:

import gzip 
from StringIO import StringIO 

# response = urllib2.urlopen(... 

content_raw = response.read() 
if 'gzip' in response.info().getheader('Content-Encoding'): 
    content = gzip.GzipFile(fileobj=StringIO(content_raw)).read() 

Когда вы имеете дело с файлом, который можно хранить либо GZIP сжатый или несжатый данные:

import gzip 

# some_file = open(... 

try: 
    content = gzip.GzipFile(fileobj=some_file).read() 
except IOError: 
    some_file.seek(0) 
    content = some_file.read() 

Примеры, приведенные выше, приведены в Python. 2.7

+0

с использованием 'try/except' с' read' на открытых буферах ввода-вывода не лучший способ вывести формат, поскольку каждая попытка может потреблять несколько байтов. –

Смежные вопросы