183 votes

Laisser l'objet JSON accepter des octets ou laisser urlopen sortir des chaînes de caractères.

Avec Python 3, je demande un document json à partir d'une URL.

response = urllib.request.urlopen(request)

Le site response est un objet de type fichier avec read y readline méthodes. Normalement, un objet JSON peut être créé avec un fichier ouvert en mode texte.

obj = json.load(fp)

Ce que je voudrais faire, c'est :

obj = json.load(response)

Cependant, cela ne fonctionne pas car urlopen renvoie un objet fichier en mode binaire.

Il existe bien sûr une solution de contournement :

str_response = response.read().decode('utf-8')
obj = json.loads(str_response)

mais ça fait mal...

Existe-t-il un meilleur moyen de transformer un objet fichier d'octets en un objet fichier de chaîne de caractères ? Ou est-ce qu'il me manque des paramètres pour l'un ou l'autre urlopen o json.load pour donner un encodage ?

102voto

La merveilleuse bibliothèque standard de Python à la rescousse

import codecs

reader = codecs.getreader("utf-8")
obj = json.load(reader(response))

Fonctionne à la fois avec py2 et py3.

Docs : Python 2 , Python3

80voto

Humphrey Bogart Points 2270

HTTP envoie des octets. Si la ressource en question est du texte, le codage des caractères est normalement spécifié, soit par l'en-tête HTTP Content-Type, soit par un autre mécanisme (une RFC, HTML meta http-equiv ,...).

urllib devrait sait comment coder les octets en une chaîne de caractères, mais c'est trop naïf - c'est une bibliothèque horriblement sous-puissante et peu pythique.

Plongez dans Python 3 fournit un aperçu de la situation.

Votre "solution de rechange" est bonne - même si elle semble mauvaise, c'est la bonne façon de procéder.

67voto

SergO Points 116

J'en suis venu à penser que la question est la meilleure réponse :)

import json
from urllib.request import urlopen

response = urlopen("site.com/api/foo/bar").read().decode('utf8')
obj = json.loads(response)

20voto

Luke Yeager Points 1132

Pour tous ceux qui essaient de résoudre ce problème en utilisant le requests bibliothèque :

import json
import requests

r = requests.get('http://localhost/index.json')
r.raise_for_status()
# works for Python2 and Python3
json.loads(r.content.decode('utf-8'))

14voto

Sarthak Gupta Points 352

Celui-ci fonctionne pour moi, j'ai utilisé la bibliothèque 'request' avec json() consultez le document dans demandes pour les humains

import requests

url = 'here goes your url'

obj = requests.get(url).json()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X