Python 2 vs. Python 3 - formats urllib

je suis vraiment fatigué d'essayer de comprendre pourquoi ce code fonctionne en Python 2 et pas en Python 3. J'essaie juste d'attraper une page de json et de l'analyser. Voici le code en Python 2:

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

I pensée le code équivalent en Python 3 serait ceci:

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

mais il explose sur mon visage, parce que les données retournées par read() sont de type" bytes". Cependant, je ne peux pas pour la vie de moi pour le convertir en quelque chose que json pourra analyser. Je sais d'après les en-têtes que reddit essaie de me renvoyer utf-8, mais je ne peux pas faire décoder les octets dans utf-8:

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

Qu'est-ce que je fais de mal?

Edit: le problème est que je ne peut pas obtenir les données dans un état utilisable, même si json charge les données, il est undisplayable, et je veux être en mesure d'imprimer les données à l'écran.

Deuxième édition: le problème a plus à voir avec l'impression qu'avec l'analyse, semble-t-il. La réponse d'Alex fournit un moyen pour le script de fonctionner en Python 3, en mettant L'IO à utf8. Mais une question demeure: pourquoi le code a-t-il fonctionné en Python 2, mais pas en Python 3?

21
demandé sur dreftymac 2010-06-28 03:50:22

3 réponses

le code que vous postez est probablement dû à de mauvaises opérations de découpage et de collage car il est clairement erroné dans les deux versions ( f.read() échoue parce qu'il n'y a pas de f barename défini).

dans Py3, ur = response.decode('utf8') fonctionne parfaitement pour moi, comme le fait la suivante json.loads(ur) . Peut-être que les mauvais copys-et-pâtes ont affecté vos tentatives de conversion de 2 à 3.

15
répondu Alex Martelli 2010-06-28 00:06:03

dépend de votre version python vous devez choisir la bibliothèque correcte.

pour python 3.5

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

pour python 2.7

import urllib
url = serviceurl + urllib.urlencode({'sensor':'false', 'address': address})   
uh = urllib.urlopen(url)
6
répondu Jose Luis Garcia 2015-11-02 16:51:39

s'il vous Plaît voir que réponse dans un autre Unicode liés à la question.

maintenant: le type Python 3 str (qui était le type Python 2 unicode ) est un objet idéalisé, dans le sens où il traite de "caractères", pas "bytes". Ces caractères, pour être utilisés pour/à partir de données de disque/réseau, doivent être encodés/décodés-à partir d'octets par une "table de conversion", A. K. a encoding A. K. une infiltration de code. En raison de la variété du système d'exploitation, Python historiquement évité de deviner ce que cet encodage devrait être; cela a changé au cours des années, mais encore le principe de "face à l'ambiguïté, refuser la tentation de deviner." appliquer.

heureusement, un serveur web facilite votre travail. Votre response ci-dessus devrait vous donner toutes les informations supplémentaires nécessaires:

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

ainsi, chaque fois que vous émettez une requête à un serveur web, vérifiez l'en-tête Content-Type Pour une valeur de charset, et décodez les données de la requête en Unicode (Python 3: bytes.decode(charset)str ) en utilisant ce jeu.

0
répondu tzot 2017-05-23 12:34:38