Python 2 vs Python 3 - urllib formats
Je suis vraiment fatigué d'essayer de comprendre pourquoi ce code fonctionne en Python 2 et pas en Python 3. Je suis juste essayer de récupérer une page de json, puis 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)
Je pensée le code équivalent en Python 3 est celle-ci:
import urllib.request, json
response = urllib.request.urlopen("http://reddit.com/.json")
content = response.read()
data = json.loads(content)
Mais il souffle dans mon visage, parce que les données renvoyées par read() est une "octets" de type. Cependant, je ne peux pas pour la vie de me convertir à quelque chose qui json sera capable d'analyser. Je sais que les en-têtes que reddit est d'essayer d'envoyer de l'utf-8 pour moi, mais je n'arrive pas à obtenir les octets de décoder en utf-8:
import urllib.request, json
response = urllib.request.urlopen("http://reddit.com/.json")
content = response.read()
data = json.loads(content.decode("utf8"))
Ce que je fais 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 edit: Le problème a plus à voir avec l'impression que l'analyse, il me semble. Alex réponse fournit un moyen pour que le script fonctionne en Python 3, en définissant les IO en utf8. Mais une question demeure: pourquoi est-ce que le code a travaillé en Python 2, mais pas de Python 3?
Vous devez vous connecter pour publier un commentaire.
Le code que vous publiez est sans doute dû à un mauvais copier-coller et des opérations, car il est clairement trompé dans les deux versions (
f.read()
échoue car il n'y a pasf
barename défini).Dans Py3,
ur = response.decode('utf8')
fonctionne parfaitement bien pour moi, tout comme le suivantjson.loads(ur)
. Peut-être le mauvais copys-et-colle affecté votre 2 à 3 tentatives de conversion.data
vous dire lajson.loads(response)
, je peuxprint
sans aucun problème (sur mon Mac Terminal.app, qui supporte l'UTF-8). Quel est votre sys.la sortie standard stdout.l'encodage? Avez-vous réglé correctement la variable d'environnementPYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr
avant de commencer Python 3? Etc, etc -- totalement différentes questions, voir.PYTHONIOENCODING
, etc) - j'ai déjà demandé à ce sujet et j'ai rien entendu de vous en réponse à cette interminable fil de commentaires, vous insistez sur la perpétuer. Pourquoi ne pas simplementprint(repr(data))
dans les deux cas et vérifier si quelque chose est différent? Si pas, alors vous savoir il est tout à propos de la sortie/terminal de questions, comme je pense qu'elle peut-être bien -- si des différences spécifiques, alors bien sûr, faites-le nous savoir (de l'édition de votre Q s'il vous plaît, pas dans un autre encore à l'étroit commentaire!-).SET PYTHONIOENCODING=utf8
.Dépend de votre version de python que vous devez choisir la bonne bibliothèque.
pour python 3.5
pour python 2.7
Veuillez voir que réponse dans un autre Unicode liés à la question.
Maintenant: le Python 3
str
(qui était le Python 2unicode
) type est un objet idéalisé, dans le sens où elle traite de “caractères”, pas “octets”. Ces personnages, afin d'être utilisé pour/à partir du disque/réseau de données, doivent être encodés en/décodé-octets par un “tableau de conversion”, un.k.un codant pour une.k.une page de codes. Parce que le système d'exploitation de la variété, Python historiquement éviter de deviner ce que l'encodage doit être; ce qui a changé au fil des ans, mais encore le principe de la “face À l'ambiguïté, à refuser la tentation de deviner.” s'applique.Heureusement, un serveur web rend votre travail plus facile. Votre
response
ci-dessus devrait vous donner toutes les informations supplémentaires nécessaires:De la sorte, chaque fois que vous émettez une requête à un serveur web, vérifiez le Type de Contenu d'en-tête pour un jeu de caractères de la valeur, et de décoder la demande de données dans Unicode (Python 3:
bytes.decode(charset)
→str
) à l'aide de ce jeu de caractères.