Подтвердить что ты не робот

Как я могу создать экземпляр GzipFile из "файла-подобного объекта", который возвращает urllib.urlopen()?

Я играю с API с помощью Python. Im пытается декодировать gzipped ответы, которые дает API.

import urllib, gzip

url = urllib.urlopen('http://api.stackoverflow.com/1.0/badges/name')
gzip.GzipFile(fileobj=url).read()

Согласно документации urllib2, urlopen "возвращает файл-подобный объект".

Однако, когда я запускаю read() на объект GzipFile, созданный с помощью Ive, я получаю эту ошибку:

AttributeError: addinfourl instance has no attribute 'tell'

Насколько я могу судить, это происходит от объекта, возвращаемого urlopen.

Кажется, он тоже не ищет, поскольку я получаю сообщение об ошибке:

url.read()
url.seek(0)

Что именно представляет собой этот объект и как создать из него функционирующий экземпляр GzipFile?

4b9b3361

Ответ 1

urlopen docs перечисляет поддерживаемые методы возвращаемого объекта. Я рекомендую обернуть объект в другом классе, который поддерживает методы, которые ожидает gzip.

Другая опция: вызвать метод чтения объекта ответа и поместить результат в объект StringIO (который должен поддерживать все методы, которые gzip ожидает). Это может быть немного дороже, хотя.

например.

import gzip
import json
import StringIO
import urllib

url = urllib.urlopen('http://api.stackoverflow.com/1.0/badges/name')
url_f = StringIO.StringIO(url.read())
g = gzip.GzipFile(fileobj=url_f)
j = json.load(g)

Ответ 2

import urllib2
import json
import gzip
import io

url='http://api.stackoverflow.com/1.0/badges/name'
page=urllib2.urlopen(url)
gzip_filehandle=gzip.GzipFile(fileobj=io.BytesIO(page.read()))
json_data=json.loads(gzip_filehandle.read())
print(json_data)

io.BytesIO для Python2.6+. Для более старых версий Python вы можете использовать cStringIO.StringIO.

Ответ 3

Вот новое обновление для ответа @stefanw, которому может показаться слишком дорогим использование такого большого количества памяти.

Благодаря этой статье (https://www.enricozini.org/blog/2011/cazzeggio/python-gzip/ она объясняет, почему gzip не работает), решение заключается в использовании Python3.

import urllib.request
import gzip

response = urllib.request.urlopen('http://api.stackoverflow.com/1.0/badges/name')
with gzip.GzipFile(fileobj=response) as f:
    for line in f:
        print(line)