Requests: UnicodeEncodeError: el códec 'latin-1' no puede codificar caracteres

Creado en 20 dic. 2013  ·  7Comentarios  ·  Fuente: psf/requests

Requests es la última versión.
Cuando intento publicar los datos que contienen caracteres chinos, se lanza esta excepción.

Traceback (most recent call last):
  File "X/threading.py", line 639, in _bootstrap_inner
  File "X/threading.py", line 596, in run
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\salesforce\api.py", line 546, in execute_anonymous
    headers=headers)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\api.py", line 88, in post
    return request('post', url, data=data, **kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\sessions.py", line 338, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\sessions.py", line 441, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\adapters.py", line 292, in send
    timeout=timeout
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\packages\urllib3\connectionpool.py", line 428, in urlopen
    body=body, headers=headers)
  File "C:\Users\Administrator\Dropbox\Sublime3056\Data\Packages\SublimeApex\requests\packages\urllib3\connectionpool.py", line 280, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "X/http/client.py", line 1049, in request
  File "X/http/client.py", line 1086, in _send_request
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 1632-1633: ordinal not in range(256)

Comentario más útil

Entonces, ST 3, pero no la revisión más reciente. Ok, eso nos da algo. Específicamente, Sublime Text 3 usa Python 3.3, no Python 2.7 (que usó Sublime Text 2). Esto significa que todas las cadenas predeterminadas en Sublime Apex son cadenas Unicode.

Si abre el archivo Python 3.3 http.client , encontrará que la función _send_request() ve así:

# Honor explicitly requested Host: and Accept-Encoding: headers.
header_names = dict.fromkeys([k.lower() for k in headers])
skips = {}
if 'host' in header_names:
    skips['skip_host'] = 1
if 'accept-encoding' in header_names:
    skips['skip_accept_encoding'] = 1

self.putrequest(method, url, **skips)

if body is not None and ('content-length' not in header_names):
    self._set_content_length(body)
for hdr, value in headers.items():
    self.putheader(hdr, value)
if isinstance(body, str):
    # RFC 2616 Section 3.7.1 says that text default has a
    # default charset of iso-8859-1.
    body = body.encode('iso-8859-1')
self.endheaders(body)

Ahora, ISO-8859-1 es un alias para Latin-1, que es el códec con el que estamos teniendo problemas. El problema que tenemos es que Sublime Apex está proporcionando un cuerpo de cadena unicode a las solicitudes, que httplib necesita codificar en bytes. Tomando el valor predeterminado de RFC 2616, concluye que desea Latin-1, que no incluye ningún carácter chino. Entonces, claramente, la codificación falla y obtiene la excepción en cuestión.

Teniendo en cuenta que Sublime Apex afirma en los encabezados que envía enviar datos codificados en UTF-8 (lo cual es una mentira actualmente), Sublime Apex quiere codificar los datos como UTF-8 antes de enviarlos. Esto significa que cualquier línea que envíe datos (en este caso, la línea 545 de salesforce/api.py ) debería leerse así:

response = requests.post(self.apex_url, soap_body.encode('utf-8'), verify=False, headers=headers)

Por el bien de cualquier otra persona que quiera confirmar mi diagnóstico, aquí hay un breve código de muestra que confirma el problema:

a = "\u13E0\u19E0\u1320"
a.encode('latin1')  # Throws UnicodeEncodeError, proves that this can't be expressed in ISO-8859-1.
a.encode('utf-8')  # Totally fine.
r = requests.post('http://httpbin.org/post', data=a)  # Using unicode string, throws UnicodeEncodeError blaming Latin1.
r = requests.post('http://httpbin.org/post', data=a.encode('utf-8'))  # Works fine.

Gracias por plantearnos esto, pero esto no es un error de Solicitudes. =)

Todos 7 comentarios

Archivo "X / http / client.py"

¿Escribiste X porque esa es una ruta a un archivo local? Si es así, la estructura de su directorio puede ser confusa urllib3. Si no es así, probablemente debería plantear esto en bugs.python.org ya que esto no es algo que creo que las solicitudes deban manejar. Parece que está aumentando de httplib (o http en Python 3, que supongo que estás usando).

@ sigmavirus24 ,

Utilicé solicitudes en el complemento sublime, si el cuerpo del jabón en la siguiente declaración no contiene ningún carácter chino, no habrá excepción.

response = requests.post(self.apex_url, soap_body, verify=False, headers=headers)

En primer lugar, a menos que esté usando una versión diferente de Sublime Apex a la de su repositorio público, Requests _no_ es la última versión, es la versión 1.2.3. ¿Puedes decirme qué versión de Sublime Text estás usando?

Es texto sublime 3056

Entonces, ST 3, pero no la revisión más reciente. Ok, eso nos da algo. Específicamente, Sublime Text 3 usa Python 3.3, no Python 2.7 (que usó Sublime Text 2). Esto significa que todas las cadenas predeterminadas en Sublime Apex son cadenas Unicode.

Si abre el archivo Python 3.3 http.client , encontrará que la función _send_request() ve así:

# Honor explicitly requested Host: and Accept-Encoding: headers.
header_names = dict.fromkeys([k.lower() for k in headers])
skips = {}
if 'host' in header_names:
    skips['skip_host'] = 1
if 'accept-encoding' in header_names:
    skips['skip_accept_encoding'] = 1

self.putrequest(method, url, **skips)

if body is not None and ('content-length' not in header_names):
    self._set_content_length(body)
for hdr, value in headers.items():
    self.putheader(hdr, value)
if isinstance(body, str):
    # RFC 2616 Section 3.7.1 says that text default has a
    # default charset of iso-8859-1.
    body = body.encode('iso-8859-1')
self.endheaders(body)

Ahora, ISO-8859-1 es un alias para Latin-1, que es el códec con el que estamos teniendo problemas. El problema que tenemos es que Sublime Apex está proporcionando un cuerpo de cadena unicode a las solicitudes, que httplib necesita codificar en bytes. Tomando el valor predeterminado de RFC 2616, concluye que desea Latin-1, que no incluye ningún carácter chino. Entonces, claramente, la codificación falla y obtiene la excepción en cuestión.

Teniendo en cuenta que Sublime Apex afirma en los encabezados que envía enviar datos codificados en UTF-8 (lo cual es una mentira actualmente), Sublime Apex quiere codificar los datos como UTF-8 antes de enviarlos. Esto significa que cualquier línea que envíe datos (en este caso, la línea 545 de salesforce/api.py ) debería leerse así:

response = requests.post(self.apex_url, soap_body.encode('utf-8'), verify=False, headers=headers)

Por el bien de cualquier otra persona que quiera confirmar mi diagnóstico, aquí hay un breve código de muestra que confirma el problema:

a = "\u13E0\u19E0\u1320"
a.encode('latin1')  # Throws UnicodeEncodeError, proves that this can't be expressed in ISO-8859-1.
a.encode('utf-8')  # Totally fine.
r = requests.post('http://httpbin.org/post', data=a)  # Using unicode string, throws UnicodeEncodeError blaming Latin1.
r = requests.post('http://httpbin.org/post', data=a.encode('utf-8'))  # Works fine.

Gracias por plantearnos esto, pero esto no es un error de Solicitudes. =)

Gracias.

r = request.post (' http://httpbin.org/post ', data = a.encode ('utf-8'))
muy útil,
¡gracias!

¿Fue útil esta página
0 / 5 - 0 calificaciones