Avec Python 3, je demande un document json à partir d'une URL.
response = urllib.request.urlopen(request)
L'objet response
est un objet de type fichier avec les méthodes read
et readline
. Normalement, un objet JSON peut être créé avec un fichier ouvert en mode texte.
obj = json.load(fp)
Ce que j'aimerais faire, c'est:
obj = json.load(response)
Cependant, cela ne fonctionne pas car urlopen renvoie un objet de fichier en mode binaire.
Un travail autour est bien sûr:
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 de fichier d'octets en un objet de fichier chaîne? Ou manque-t-il des paramètres pour que urlopen
ou json.load
donne un codage?
HTTP envoie des octets. Si la ressource en question est du texte, le codage de caractères est normalement spécifié, soit par l'en-tête HTTP Content-Type, soit par un autre mécanisme (un RFC, HTML meta http-equiv
, ...).
urllib
devrait savoir comment coder les octets en chaîne, mais c'est trop naïf - c'est une bibliothèque horriblement sous-puissante et non pythonique.
Plongez dans Python donne un aperçu de la situation.
Votre "solution de rechange" va bien - même si vous vous sentez mal, c'est la bonne façon de le faire.
Je suis venu à l'opinion 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)
Pour tous ceux qui essaient de résoudre ce problème en utilisant la bibliothèque requests
:
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'))
Celui-ci fonctionne pour moi, j'ai utilisé la bibliothèque 'request' avec json()
consultez le doc dans demandes pour des humains
import requests
url = 'here goes your url'
obj = requests.get(url).json()
J'ai rencontré des problèmes similaires avec Python 3.4.3 & 3.5.2 et Django 1.11.3. Cependant, lors de la mise à niveau vers Python 3.6.1, les problèmes ont disparu.
Vous pouvez en savoir plus à ce sujet ici: https://docs.python.org/3/whatsnew/3.6.html#json
Si vous n'êtes pas lié à une version spécifique de Python, envisagez simplement de passer à la version 3.6 ou ultérieure.
Si vous rencontrez ce problème lorsque vous utilisez le microframework flask, vous pouvez simplement effectuer les opérations suivantes:
data = json.loads(response.get_data(as_text=True))
From the docs : "Si as_text est défini sur True, la valeur de retour sera une chaîne unicode décodée"
Votre solution de contournement vient de me sauver. J'avais beaucoup de problèmes à traiter la demande en utilisant le framework Falcon. Cela a fonctionné pour moi. req étant le formulaire de demande curl pr httpie
json.loads(req.stream.read().decode('utf-8'))
Je viens de trouver cette méthode simple pour créer du contenu HttpResponse en json
import json
request = RequestFactory() # ignore this, this just like your request object
response = MyView.as_view()(request) # got response as HttpResponse object
response.render() # call this so we could call response.content after
json_response = json.loads(response.content.decode('utf-8'))
print(json_response) # {"your_json_key": "your json value"}
J'espère que ça vous aide
Cela va diffuser les données d'octet dans JSON.
import io
obj = json.load(io.TextIOWrapper(response))
io.TextIOWrapper est préférable au lecteur de module du codec. https://www.python.org/dev/peps/pep-0400/