2010-06-27 31 views
21

Ben bu kod Python 2'de çalışmaktadır ve Python 3'te sadece json bir sayfasını kapmak ve sonra ayrıştırmak çalışıyorum değil neden anlamaya çalışmakla gerçekten yorulmadan o.Python 2 vs Python 3 - urllib formatları

import urllib, json 
response = urllib.urlopen("http://reddit.com/.json") 
content = response.read() 
data = json.loads(content) 

Ben Python 3'te eşdeğer kod bu olurdu düşünce: Burada Python 2'de kod

import urllib.request, json 
response = urllib.request.urlopen("http://reddit.com/.json") 
content = response.read() 
data = json.loads(content) 

Ama, yüzüme patlarsa çünkü okuma döndürdüğü verileri () bir "bayt" türüdür. Ancak, hayatım boyunca jsonun ayrıştırabileceği bir şeye dönüşmesini sağlayamam. Ben reddit bana geri utf-8 göndermeye çalışıyor başlıklarından biliyorum, ama bayt utf-8 içine çözmek için almak gibi olamaz: Neyi yanlış yapıyorum

import urllib.request, json 
response = urllib.request.urlopen("http://reddit.com/.json") 
content = response.read() 
data = json.loads(content.decode("utf8")) 

?

Düzenleme: Sorun, verileri kullanılabilir bir duruma alamam; json veriyi yüklese de, bunun bir kısmı çözülemez ve verileri ekrana yazdırabilmek istiyorum.

İkinci düzenleme: Sorun ayrıştırma daha baskı yapmak için daha fazla vardır, öyle görünüyor. Alex'in cevabı, IO'yu utf8'e ayarlayarak, betiğin Python 3'te çalışması için bir yol sağlar. Ama yine de bir soru var: neden kod Python 2'de çalışmış, Python 3 değil?

cevap

15

Yüklediğiniz kod, büyük olasılıkla yanlış kesme ve yapıştırma işlemlerinden kaynaklandığından, her iki sürümde de açıkça yanlış olduğu için (f.read() başarısız olduğu için f barename tanımlanmamıştır).

Py3'te ur = response.decode('utf8'), aşağıdaki json.loads(ur)'da olduğu gibi benim için de gayet iyi çalışır. Belki de yanlış copys-and-pastes 2-to-3 dönüşüm girişimlerinizi etkiledi.

+0

Kod hatalarını düzeltebilirim ... Ekranı yeniden biçimlendirmeyi denedim, ancak işlemin hepsini batırdım. : P Yine de, ben ayrıştırdıktan sonra verileri görüntüleyemiyorum (basit bir "yazdırma (veri)" kullanarak), çünkü bana charmap hataları veriyor. –

+0

@Daniel, problemleri _after_ elde ettiniz, bu verilerden veri almakla ilgili ayrı bir soru gibi görünüyor (ki benim cevabım, göründü, yanıt verdi - yine de kabul etmiyor olsanız da, siz yapmadıysanız) t bile onu kışkırt!). Eğer "data" ile "json.loads (response)" demek istediyseniz, herhangi bir sorun olmadan yazdırabilirim (UTF-8'i destekleyen Mac Terminal.app'ımda). Sys.stdout.encoding'iniz nedir? Python 3'ü başlatmadan önce "PYTHONIOENCODING" ortam değişkenini doğru olarak ayarladınız mı: Stdin/stdout/stderr' için kullanılan kodlama [: errors]? Vb, vb - tamamen farklı konular, bkz. –

+0

İlk başta belirsiz olsaydım özür dilerim. Çekirdek problemi, her ne sebeple olursa olsun, ayrıştırmadan sonra verileri kullanamıyorum * (yazdırma sadece bir başlangıcıdır; yazdıramıyorsam, o zaman satırın aşağısında bir yerde başım belaya girer) veri okuma). Kodlamayı kontrol edeceğim, W7 makinemde çalışmadığını söylemek yeterli. –

0

başka Unicode ilgili söz konusu that cevaba bakınız.

Şimdi: Python 3 str (hangi Python 2 unicode idi) türü, "bytes" değil "karakterlerle" ilgilenmesi anlamında idealleştirilmiş bir nesnedir. Bu karakterlerin, disk/ağ verisi için/disk veriden kullanılmak üzere, bir "dönüşüm tablosu", a.k.a kodlayan bir kod dizisi tarafından bayttan şifrelenmesi gerekir. İşletim sistemi çeşitliliği nedeniyle, Python geçmiş kodlamanın ne olması gerektiğini tahmin etmekten kaçındı; bu yıllar içinde değişiyor, ama yine de “belirsizlik karşısında, tahmin etme isteğini reddetme” ilkesi geçerlidir.

Neyse ki bir web sunucusu işinizi kolaylaştırır. (

>>> response.headers['content-type'] 
'application/json; charset=UTF-8' 

Yani, her zaman bir charset değeri için Content-Type başlığını kontrol, bir web sunucusuna bir istek, sorun ve Unicode içine isteğin verilerini deşifre: Yukarıdaki Kişisel response size gerekli tüm ek bilgileri vermelidir Python 3: bytes.decode(charset)str) o karakter kümesini kullanarak.

6

Python sürümünüze bağlı olarak doğru kitaplığı seçmeniz gerekir. piton 2 için piton 3,5

import urllib.request 
data = urllib.request.urlopen(url).read().decode('utf8') 

için

.7

import urllib 
url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address}) 
uh = urllib.urlopen(url) 
+0

Kodunuzu açıklığa kavuşturmak için bir açıklama isteyebilirsiniz. – GabrielOshiro