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 ?

7voto

PaulMest Points 2381

J'ai rencontré des problèmes similaires avec Python 3.4.3 et 3.5.2 et Django 1.11.3. Cependant, lorsque j'ai effectué la mise à jour 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.

3voto

cs_stackX Points 296

Si vous rencontrez ce problème lors de l'utilisation du micro-framework flask, vous pouvez tout simplement le faire :

data = json.loads(response.get_data(as_text=True))

Extrait de la documentation : "Si as_text est défini à True, la valeur de retour sera une chaîne unicode décodée".

1voto

thielyrics Points 41

Votre solution de contournement vient de me sauver. J'avais beaucoup de problèmes pour traiter la demande en utilisant le cadre Falcon. Ceci a fonctionné pour moi. req étant le formulaire de requête curl pr httpie

json.loads(req.stream.read().decode('utf-8'))

1voto

Collin Anderson Points 952

Cela va transformer les données en octets en json.

import io

obj = json.load(io.TextIOWrapper(response))

io.TextIOWrapper est préféré au lecteur de module du codec. https://www.python.org/dev/peps/pep-0400/

1voto

eugene y Points 37378

A partir de Python 3.6, vous pouvez utiliser json.loads() pour désérialiser un bytes directement (l'encodage doit être UTF-8, UTF-16 ou UTF-32). Ainsi, en utilisant uniquement des modules de la bibliothèque standard, vous pouvez faire :

import json
from urllib import request

response = request.urlopen(url).read()
data = json.loads(response)

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