Con Python 3 solicito un documento json desde una URL.
response = urllib.request.urlopen(request)
El response
objeto es un objeto tipo archivo con read
y readline
métodos. Normalmente, un objeto JSON se puede crear con un archivo abierto en modo de texto.
obj = json.load(fp)
Lo que me gustaría hacer es:
obj = json.load(response)
Sin embargo, esto no funciona ya que urlopen devuelve un objeto de archivo en modo binario.
Una solución es, por supuesto:
str_response = response.read().decode('utf-8')
obj = json.loads(str_response)
pero esto se siente mal ...
¿Hay una mejor manera de transformar un objeto de archivo de bytes en un objeto de archivo de cadena? ¿O me faltan parámetros para urlopen
o json.load
para dar una codificación?
Respuestas:
HTTP envía bytes. Si el recurso en cuestión es texto, la codificación de caracteres normalmente se especifica, ya sea por el encabezado HTTP Content-Type o por otro mecanismo (un RFC, HTML
meta http-equiv
, ...).urllib
debería saber cómo codificar los bytes en una cadena, pero es demasiado ingenuo, es una biblioteca horriblemente poco poderosa y poco pitónica.Sumérgete en Python 3 proporciona una visión general sobre la situación.
Su "solución" está bien, aunque se siente mal, es la forma correcta de hacerlo.
fuente
urlopen
debería poder decodificar los bytes, ya que conoce la codificación. De todos modos, he publicado la solución de biblioteca estándar de Python como respuesta: puede hacer la decodificación de bytes de transmisión mediante elcodecs
módulo.La maravillosa biblioteca estándar de Python al rescate ...
Funciona con py2 y py3.
Documentos: Python 2 , Python3
fuente
python 3.4.3
no estoy seguro de por qué? El error fueTypeError: the JSON object must be str, not 'StreamReader'
json.loads()
lugar dejson.load()
?response.headers.get_content_charset()
. DevuelveNone
si no hay codificación y no existe en python2.He llegado a la opinión de que la pregunta es la mejor respuesta :)
fuente
Para cualquier otra persona que intente resolver esto usando la
requests
biblioteca:fuente
requests
: simplemente puede hacerr.json()
json.loads
. Todo lo que tienes que hacer es quer.json()
ya tienes tu objeto JSON cargado en un dict.*** UnicodeEncodeError: 'ascii' codec can't encode characters in position 264-265: ordinal not in range(128)
Este funciona para mí, utilicé la biblioteca 'request' con
json()
el documento en solicitudes para humanosfuente
Me encontré con problemas similares usando Python 3.4.3 y 3.5.2 y Django 1.11.3. Sin embargo, cuando actualicé a Python 3.6.1 los problemas desaparecieron.
Puede leer más sobre esto aquí: https://docs.python.org/3/whatsnew/3.6.html#json
Si no está vinculado a una versión específica de Python, solo considere actualizar a 3.6 o posterior.
fuente
Si tiene este problema mientras usa el matraz de matraz, entonces puede hacer lo siguiente:
data = json.loads(response.get_data(as_text=True))
De los documentos : "Si as_text se establece en True, el valor de retorno será una cadena unicode decodificada"
fuente
Su solución en realidad solo me salvó. Estaba teniendo muchos problemas para procesar la solicitud usando el marco Falcon. Esto funcionó para mí. req siendo el formulario de solicitud curl pr httpie
fuente
Esto transmitirá los datos de bytes a json.
Se prefiere io.TextIOWrapper al lector de módulos del códec. https://www.python.org/dev/peps/pep-0400/
fuente
json.loads(bytes_obj.decode())
.Acabo de encontrar este método simple para hacer contenido HttpResponse como json
Espero que te ayude
fuente
A partir de Python 3.6, puede usar
json.loads()
para deserializar unbytes
objeto directamente (la codificación debe ser UTF-8, UTF-16 o UTF-32). Entonces, usando solo módulos de la biblioteca estándar, puede hacer:fuente
Utilicé el siguiente programa para usar
json.loads()
fuente