2010-11-17 4 views
13

Używam interfejsu API przepełnienia stosu przy użyciu Pythona. Próbuję odszyfrować spakowane przez gzip odpowiedzi, które daje interfejs API.Jak utworzyć instancję GzipFile z "obiektu podobnego do pliku", który zwraca funkcja urllib.urlopen()?

import urllib, gzip 

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

Według the urllib2 documentation, urlopen „zwraca obiekt plikopodobny”.

Jednak, gdy biegnę read() na obiekcie GzipFile Utworzyłem go używać, otrzymuję ten błąd:

AttributeError: addinfourl instance has no attribute 'tell' 

O ile mogę powiedzieć, to jest pochodzących z obiektu zwróconego przez urlopen.

Nie wydaje się, aby szukać albo, jak pojawia się błąd, kiedy to zrobić:

url.read() 
url.seek(0) 

Czym dokładnie jest ten przedmiot, i jak mogę stworzyć funkcjonujący GzipFile wystąpienie z niej?

+1

'Content-Encoding: gzip' powinien być obsługiwany przez bibliotekę http, ale niestety tak nie jest. To jest [problem 9500] (http://bugs.python.org/issue9500) w bazie danych błędów Pythona dla zainteresowanych. –

+0

@Magnus: Pozdrawiam, dobrze wiedzieć, że to przynajmniej w tropiku błędów. –

Odpowiedz

10

Lista urlopen docs zawiera listę obsługiwanych metod zwracanego obiektu. Polecam zawijanie obiektu w innej klasie obsługującej metody oczekiwane przez gzip.

Inna opcja: wywołaj metodę odczytu obiektu odpowiedzi i umieść wynik w obiekcie StringIO (który powinien obsługiwać wszystkie metody oczekiwane przez gzip). To może trochę droższe.

E.g.

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) 
+0

Zawijanie go w obiekt 'StringIO' mija ten błąd, ale nadal otrzymuję plik' IOError: Not a gzipped' –

+1

@ThomasK To działa dla mnie. Czy przekazujesz 'url.read()' do konstruktora 'StringIO' lub po prostu' url'? Ten ostatni się nie udaje. – aaronasterling

+0

Tak, właśnie to zrobiłem źle. Dzięki. –

8
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 jest dla python2.6 +. W starszych wersjach Pythona możesz użyć cStringIO.StringIO.

Powiązane problemy