W Pythonie 3 żądam dokumentu json z adresu URL.
response = urllib.request.urlopen(request)
response
Obiekt jest obiektem plikopodobnym z read
i readline
metody. Zwykle obiekt JSON można utworzyć za pomocą pliku otwartego w trybie tekstowym.
obj = json.load(fp)
Chciałbym:
obj = json.load(response)
To jednak nie działa, ponieważ urlopen zwraca obiekt pliku w trybie binarnym.
Obejście to oczywiście:
str_response = response.read().decode('utf-8')
obj = json.loads(str_response)
ale to jest złe ...
Czy istnieje lepszy sposób na przekształcenie obiektu pliku bajtów w obiekt pliku ciągu? A może brakuje mi jakichkolwiek parametrów dla jednego z nich urlopen
lub json.load
dla podania kodowania?
Odpowiedzi:
HTTP wysyła bajty. Jeśli dany zasób jest tekstem, kodowanie znaków jest zwykle określane przez nagłówek HTTP Content-Type lub inny mechanizm (RFC, HTML
meta http-equiv
, ...).urllib
Powinien wiedzieć, jak zakodować bajty do łańcucha, ale jest to zbyt naiwne - to strasznie niedopasowana i nie-Pythonowa biblioteka.Dive Into Python 3 zawiera przegląd sytuacji.
Twoje „obejście” jest w porządku - chociaż wydaje się niewłaściwe, jest to właściwy sposób, aby to zrobić.
źródło
urlopen
powinien być w stanie dekodować same bajty, ponieważ zna kodowanie. W każdym razie, jako odpowiedź zamieściłem rozwiązanie biblioteki standardowej Pythona - za pomocącodecs
modułu możesz wykonać strumieniowe dekodowanie bajtów .Z pomocą przychodzi wspaniała standardowa biblioteka Pythona…
Działa z py2 i py3.
Dokumenty: Python 2 , Python3
źródło
python 3.4.3
nie wiem dlaczego? Błąd był następującyTypeError: the JSON object must be str, not 'StreamReader'
json.loads()
zamiastjson.load()
?response.headers.get_content_charset()
. Zwraca,None
jeśli nie ma kodowania i nie istnieje w python2.Doszedłem do wniosku, że pytanie jest najlepszą odpowiedzią :)
źródło
Dla każdego, kto próbuje rozwiązać ten problem za pomocą
requests
biblioteki:źródło
requests
: możesz po prostu zrobićr.json()
json.loads
. Wszystko, co musisz zrobić, tor.json()
załadować już swój obiekt JSON do dyktu.*** UnicodeEncodeError: 'ascii' codec can't encode characters in position 264-265: ordinal not in range(128)
Ten działa dla mnie, użyłem biblioteki „request”, aby
json()
sprawdzić dokument w prośbach dla ludziźródło
Napotkałem podobne problemy używając Pythona 3.4.3 i 3.5.2 oraz Django 1.11.3. Jednak po uaktualnieniu do Pythona 3.6.1 problemy zniknęły.
Możesz przeczytać więcej na ten temat tutaj: https://docs.python.org/3/whatsnew/3.6.html#json
Jeśli nie jesteś przywiązany do konkretnej wersji Pythona, rozważ uaktualnienie do wersji 3.6 lub nowszej.
źródło
Jeśli masz ten problem podczas korzystania z microframework flask, możesz po prostu:
data = json.loads(response.get_data(as_text=True))
Z dokumentacji : „Jeśli as_text ma wartość True, wartość zwracana będzie zdekodowanym ciągiem znaków Unicode”
źródło
Twoje obejście właśnie mnie uratowało. Miałem wiele problemów z przetwarzaniem żądania przy użyciu frameworka Falcon. To zadziałało dla mnie. req to formularz zapytania curl pr httpie
źródło
Spowoduje to przesłanie danych bajtowych do json.
io.TextIOWrapper jest preferowany w stosunku do czytnika modułu kodeka. https://www.python.org/dev/peps/pep-0400/
źródło
json.loads(bytes_obj.decode())
.Właśnie znalazłem tę prostą metodę tworzenia zawartości HttpResponse jako pliku json
Mam nadzieję, że ci to pomoże
źródło
Począwszy od Pythona 3.6, możesz użyć
json.loads()
dobytes
bezpośredniej deserializacji obiektu (kodowanie musi być UTF-8, UTF-16 lub UTF-32). Tak więc, używając tylko modułów z biblioteki standardowej, możesz:źródło
Użyłem poniższego programu do korzystania z
json.loads()
źródło