Requests: UnicodeEncodeError: 'Latin-1'-Codec kann keine Zeichen codieren

Erstellt am 20. Dez. 2013  ·  7Kommentare  ·  Quelle: psf/requests

Anfragen ist die neueste Version.
Wenn ich versuche, die Daten zu posten, die chinesische Zeichen enthalten, wird diese Ausnahme ausgelöst.

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)

Hilfreichster Kommentar

Also ST 3, aber nicht die neueste Überarbeitung. Ok, das gibt uns etwas. Insbesondere verwendet Sublime Text 3 Python 3.3, nicht Python 2.7 (das von Sublime Text 2 verwendet wurde). Dies bedeutet, dass alle Standardzeichenfolgen in Sublime Apex Unicode-Zeichenfolgen sind.

Wenn Sie die Datei http.client Python 3.3 öffnen, werden Sie feststellen, dass die Funktion _send_request() wie folgt aussieht:

# 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)

ISO-8859-1 ist ein Alias ​​für Latin-1, mit dem wir Probleme haben. Das Problem, das wir haben, ist, dass Sublime Apex einen Unicode-String-Body für Requests bereitstellt, den httplib in Bytes codieren muss. Nimmt man die Vorgabe aus RFC 2616, kommt man zu dem Schluss, dass man Latin-1 will, das keine chinesischen Zeichen enthält. Dann schlägt die Codierung offensichtlich fehl und Sie erhalten die fragliche Ausnahme.

In Anbetracht dessen, dass Sublime Apex in den von ihm gesendeten Headern behauptet, UTF-8-codierte Daten zu senden (was derzeit eine Lüge ist), möchte Sublime Apex die Daten vor dem Senden als UTF-8 codieren. Dies bedeutet, dass jede Zeile, die Daten sendet (in diesem Fall Zeile 545 von salesforce/api.py ), wie folgt lauten sollte:

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

Für alle anderen, die meine Diagnose bestätigen möchten, hier ein kurzer Beispielcode, der das Problem bestätigt:

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.

Vielen Dank, dass Sie dies bei uns angesprochen haben, aber dies ist kein Requests-Fehler. =)

Alle 7 Kommentare

Datei "X/http/client.py"

Haben Sie X weil dies ein Pfad zu einer lokalen Datei ist? Wenn dies der Fall ist, kann Ihre Verzeichnisstruktur urllib3 verwirren. Wenn nicht, sollten Sie dies wahrscheinlich auf bugs.python.org melden, da dies meiner Meinung nach nicht etwas ist, das Anfragen bearbeitet werden sollten. Dies sieht so aus, als ob es von httplib (oder http auf Python 3, das Sie vermutlich verwenden) steigt.

@sigmavirus24 ,

Ich habe Anfragen im Sublime-Plugin verwendet, wenn die Seifenkörper in der folgenden Anweisung keine chinesischen Zeichen enthält, gibt es keine Ausnahme.

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

Erstens ist Requests _nicht_ die neueste Version, es ist Version 1.2.3, es sei denn, Sie verwenden eine andere Version von Sublime Apex als die in ihrem öffentlichen Repository. Können Sie mir sagen, welche Version von Sublime Text Sie verwenden?

Es ist erhabener Text 3056

Also ST 3, aber nicht die neueste Überarbeitung. Ok, das gibt uns etwas. Insbesondere verwendet Sublime Text 3 Python 3.3, nicht Python 2.7 (das von Sublime Text 2 verwendet wurde). Dies bedeutet, dass alle Standardzeichenfolgen in Sublime Apex Unicode-Zeichenfolgen sind.

Wenn Sie die Datei http.client Python 3.3 öffnen, werden Sie feststellen, dass die Funktion _send_request() wie folgt aussieht:

# 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)

ISO-8859-1 ist ein Alias ​​für Latin-1, mit dem wir Probleme haben. Das Problem, das wir haben, ist, dass Sublime Apex einen Unicode-String-Body für Requests bereitstellt, den httplib in Bytes codieren muss. Nimmt man die Vorgabe aus RFC 2616, kommt man zu dem Schluss, dass man Latin-1 will, das keine chinesischen Zeichen enthält. Dann schlägt die Codierung offensichtlich fehl und Sie erhalten die fragliche Ausnahme.

In Anbetracht dessen, dass Sublime Apex in den von ihm gesendeten Headern behauptet, UTF-8-codierte Daten zu senden (was derzeit eine Lüge ist), möchte Sublime Apex die Daten vor dem Senden als UTF-8 codieren. Dies bedeutet, dass jede Zeile, die Daten sendet (in diesem Fall Zeile 545 von salesforce/api.py ), wie folgt lauten sollte:

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

Für alle anderen, die meine Diagnose bestätigen möchten, hier ein kurzer Beispielcode, der das Problem bestätigt:

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.

Vielen Dank, dass Sie dies bei uns angesprochen haben, aber dies ist kein Requests-Fehler. =)

Vielen Dank.

r = request.post(' http://httpbin.org/post ', data=a.encode('utf-8'))
sehr hilfreich,
Danke schön!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen