Mit Python 3 fordere ich ein JSON-Dokument von einer URL an.
response = urllib.request.urlopen(request)
Das response
Objekt ist ein dateiähnliches Objekt mit read
und readline
Methoden. Normalerweise kann ein JSON-Objekt mit einer im Textmodus geöffneten Datei erstellt werden.
obj = json.load(fp)
Was ich tun möchte ist:
obj = json.load(response)
Dies funktioniert jedoch nicht, da urlopen ein Dateiobjekt im Binärmodus zurückgibt.
Eine Umgehung ist natürlich:
str_response = response.read().decode('utf-8')
obj = json.loads(str_response)
aber das fühlt sich schlecht an ...
Gibt es eine bessere Möglichkeit, ein Byte-Dateiobjekt in ein String-Dateiobjekt umzuwandeln? Oder fehlen mir Parameter für eine urlopen
oder json.load
eine Kodierung?
Antworten:
HTTP sendet Bytes. Wenn es sich bei der fraglichen Ressource um Text handelt, wird die Zeichenkodierung normalerweise entweder durch den HTTP-Header vom Inhaltstyp oder durch einen anderen Mechanismus (RFC, HTML
meta http-equiv
, ...) angegeben.urllib
sollte wissen, wie man die Bytes in einen String codiert, aber es ist zu naiv - es ist eine schrecklich unterversorgte und nicht pythonische Bibliothek.Dive Into Python 3 bietet einen Überblick über die Situation.
Ihr "Workaround" ist in Ordnung - obwohl es sich falsch anfühlt, ist es der richtige Weg, dies zu tun.
quelle
urlopen
in der Lage sein sollte, die Bytes selbst zu decodieren, da es die Codierung kennt. Wie auch immer, ich habe die Python-Standardbibliothekslösung als Antwort veröffentlicht - Sie können mithilfe descodecs
Moduls die Streaming-Dekodierung von Bytes durchführen .Pythons wunderbare Standardbibliothek zur Rettung…
Funktioniert sowohl mit py2 als auch mit py3.
Dokumente : Python 2 , Python3
quelle
python 3.4.3
mir nicht sicher, warum? Der Fehler warTypeError: the JSON object must be str, not 'StreamReader'
json.loads()
statt verwendetjson.load()
?response.headers.get_content_charset()
. Gibt zurück,None
wenn keine Codierung vorhanden ist und auf python2 nicht vorhanden ist.Ich bin zu dem Schluss gekommen, dass die Frage die beste Antwort ist :)
quelle
Für alle anderen, die versuchen, dies mithilfe der
requests
Bibliothek zu lösen :quelle
requests
: Sie können einfach tunr.json()
json.loads
. Sie müssenr.json()
lediglich Ihr JSON-Objekt bereits in ein Diktat geladen haben.*** UnicodeEncodeError: 'ascii' codec can't encode characters in position 264-265: ordinal not in range(128)
Dieser funktioniert für mich. Ich habe die 'Anforderungs'-Bibliothek verwendet
json()
, um das Dokument in Anfragen für Menschen auszucheckenquelle
Ich bin mit Python 3.4.3 & 3.5.2 und Django 1.11.3 auf ähnliche Probleme gestoßen. Als ich jedoch auf Python 3.6.1 aktualisierte, verschwanden die Probleme.
Weitere Informationen finden Sie hier: https://docs.python.org/3/whatsnew/3.6.html#json
Wenn Sie nicht an eine bestimmte Version von Python gebunden sind, sollten Sie ein Upgrade auf 3.6 oder höher in Betracht ziehen.
quelle
Wenn dieses Problem bei der Verwendung des Kolben-Mikroframeworks auftritt, können Sie Folgendes tun:
data = json.loads(response.get_data(as_text=True))
Aus den Dokumenten : "Wenn as_text auf True gesetzt ist, ist der Rückgabewert eine decodierte Unicode-Zeichenfolge."
quelle
Ihre Problemumgehung hat mich gerade gerettet. Ich hatte viele Probleme bei der Verarbeitung der Anfrage mit dem Falcon-Framework. Das hat bei mir funktioniert. req ist das Anfrageformular curl pr httpie
quelle
Dadurch werden die Byte-Daten in json gestreamt.
io.TextIOWrapper wird dem Modulleser des Codecs vorgezogen. https://www.python.org/dev/peps/pep-0400/
quelle
json.loads(bytes_obj.decode())
.Ich habe gerade diese einfache Methode gefunden, um HttpResponse-Inhalte als JSON zu erstellen
Hoffe das hilft dir
quelle
Ab Python 3.6 können Sie
json.loads()
einbytes
Objekt direkt deserialisieren (die Codierung muss UTF-8, UTF-16 oder UTF-32 sein). Wenn Sie also nur Module aus der Standardbibliothek verwenden, können Sie Folgendes tun:quelle
Ich habe unten Programm verwendet, um zu verwenden
json.loads()
quelle