2010-11-17 13 views
13

Tôi đang chơi xung quanh với API ngăn xếp ngăn xếp bằng cách sử dụng Python. Tôi đang cố gắng giải mã các câu trả lời được gzipped mà API cung cấp.Làm cách nào để tạo một cá thể GzipFile từ "đối tượng giống như tệp" mà urllib.urlopen() trả về?

import urllib, gzip 

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

Theo trả về the urllib2 documentation, urlopen “trả về một đối tượng giống như tệp”.

Tuy nhiên, khi tôi chạy read() trên đối tượng GzipFile tôi đã tạo ra sử dụng nó, tôi nhận được lỗi này:

AttributeError: addinfourl instance has no attribute 'tell' 

Theo như tôi có thể nói, đây là đến từ các đối tượng được trả về bởi urlopen.

Nó không xuất hiện để có tìm kiếm một trong hai, như tôi nhận được một lỗi khi tôi làm điều này:

url.read() 
url.seek(0) 

gì chính xác là đối tượng này, và làm thế nào để tạo ra một hoạt động GzipFile dụ từ nó?

+1

'Nội dung Mã hóa: gzip' phải được xử lý bởi thư viện http nhưng tiếc là không phải. Đây là [vấn đề 9500] (http://bugs.python.org/issue9500) trong cơ sở dữ liệu lỗi của Python, vì sự quan tâm. –

+0

@Magnus: chúc mừng, rất vui được biết ít nhất là trong trình theo dõi lỗi. –

Trả lời

10

urlopen docs liệt kê các phương thức được hỗ trợ của đối tượng được trả về. Tôi khuyên bạn nên gói đối tượng trong lớp khác hỗ trợ các phương thức mà gzip mong đợi.

Tùy chọn khác: gọi phương thức đọc của đối tượng phản hồi và đặt kết quả trong đối tượng StringIO (cần hỗ trợ tất cả các phương thức mà gzip mong đợi). Điều này có thể tốn kém hơn một chút.

Ví dụ:

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

Gói nó trong một đối tượng 'StringIO' vượt qua lỗi đó, nhưng tôi vẫn nhận được một' IOError: Không phải là một tập tin nén ' –

+1

@ThomasK Nó hoạt động tìm cho tôi. Bạn đang truyền 'url.read()' vào hàm tạo StringIO' hay chỉ là 'url'? Cái sau không thành công. – aaronasterling

+0

Yup, đó là những gì tôi đã sai. Cảm ơn. –

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 là dành cho python2.6 +. Đối với các phiên bản cũ hơn của Python, bạn có thể sử dụng cStringIO.StringIO.