Avec Python 3, je demande un document json à partir d'une URL.
response = urllib.request.urlopen(request)
L' response
objet est un objet de type fichier avec des 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 je voudrais faire, c'est:
obj = json.load(response)
Cela ne fonctionne cependant pas car urlopen renvoie un objet fichier en mode binaire.
Un contournement est bien sûr:
str_response = response.read().decode('utf-8')
obj = json.loads(str_response)
mais ça fait du mal ...
Existe-t-il un meilleur moyen de transformer un objet de fichier d'octets en un objet de fichier de chaîne? Ou est-ce que je manque des paramètres pour l'un urlopen
ou l' autre json.load
pour donner un encodage?
Réponses:
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 (un RFC, HTML
meta http-equiv
, ...).urllib
devrait savoir encoder les octets dans une chaîne, mais c'est trop naïf - c'est une bibliothèque horriblement sous-alimentée et non pythonique.Dive Into Python 3 donne un aperçu de la situation.
Votre "contournement" est bien - même si cela semble mal, c'est la bonne façon de le faire.
la source
urlopen
devrait être capable de décoder les octets lui-même car il connaît l'encodage. Quoi qu'il en soit, j'ai publié la solution de bibliothèque standard Python comme réponse - vous pouvez effectuer un décodage en continu des octets à l'aide ducodecs
module.La merveilleuse bibliothèque standard de Python à la rescousse…
Fonctionne avec py2 et py3.
Documents: Python 2 , Python3
la source
python 3.4.3
ne sais pas pourquoi? L'erreur étaitTypeError: the JSON object must be str, not 'StreamReader'
json.loads()
place dejson.load()
?response.headers.get_content_charset()
. RenvoieNone
s'il n'y a pas d'encodage et n'existe pas sur python2.Je suis arrivé à l'opinion que la question est la meilleure réponse :)
la source
Pour quiconque essaie de résoudre ce problème en utilisant la
requests
bibliothèque:la source
requests
: vous pouvez simplement fairer.json()
json.loads
. Tout ce que vous avez à faire estr.json()
que votre objet JSON est déjà chargé dans un dict.*** UnicodeEncodeError: 'ascii' codec can't encode characters in position 264-265: ordinal not in range(128)
Celui-ci fonctionne pour moi, j'ai utilisé la bibliothèque de `` demande '' avec
json()
vérifier le document dans les demandes pour les humainsla source
J'ai rencontré des problèmes similaires en utilisant Python 3.4.3 & 3.5.2 et Django 1.11.3. Cependant, lorsque j'ai mis à niveau vers Python 3.6.1, les problèmes ont disparu.
Vous pouvez en savoir plus 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.
la source
Si vous rencontrez ce problème lors de l'utilisation du microframework flask, vous pouvez simplement faire:
data = json.loads(response.get_data(as_text=True))
D'après la documentation : "Si as_text est défini sur True, la valeur de retour sera une chaîne Unicode décodée"
la source
Votre solution de contournement vient de me sauver. J'avais beaucoup de problèmes à traiter la requête en utilisant le framework Falcon. Cela a fonctionné pour moi. req étant le formulaire de demande curl pr httpie
la source
Cela diffusera les données d'octet dans json.
io.TextIOWrapper est préférable au lecteur de module du codec. https://www.python.org/dev/peps/pep-0400/
la source
json.loads(bytes_obj.decode())
.Je viens de trouver cette méthode simple pour créer du contenu HttpResponse en tant que json
J'espère que cela vous aide
la source
Depuis Python 3.6, vous pouvez utiliser
json.loads()
pour désérialiser unbytes
objet directement (l'encodage doit être UTF-8, UTF-16 ou UTF-32). Ainsi, en utilisant uniquement les modules de la bibliothèque standard, vous pouvez faire:la source
J'ai utilisé le programme ci-dessous pour utiliser
json.loads()
la source