Requests: UnicodeEncodeError: 'latin-1' 编解码器无法编码字符

创建于 2013-12-20  ·  7评论  ·  资料来源: psf/requests

请求是最新版本。
当我尝试发布包含汉字的数据时,抛出此异常。

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)

最有用的评论

所以,ST 3,但不是最新的修订版。 好的,这给了我们一些东西。 具体来说,Sublime Text 3 使用 Python 3.3,而不是 Python 2.7(Sublime Text 2 使用的)。 这意味着 Sublime Apex 中的所有默认字符串都是 unicode 字符串。

如果打开 Python 3.3 http.client文件,您会发现_send_request()函数如下所示:

# 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 是 Latin-1 的别名,这是我们遇到问题的编解码器。 我们遇到的问题是 Sublime Apex 为请求提供了一个 unicode 字符串主体,httplib 需要将其编码为字节。 使用 RFC 2616 中的默认值,它得出结论您需要 Latin-1,其中不包含任何中文字符。 很明显,编码失败,你会得到有问题的异常。

考虑到 Sublime Apex 在其发送的标头中声称要发送 UTF-8 编码数据(目前这是谎言),Sublime Apex 希望在发送数据之前将数据编码为 UTF-8。 这意味着任何发送数据的行(在本例中为salesforce/api.py 545 行)应如下所示:

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

为了其他想要确认我的诊断的人,这里有一小段可以确认问题的示例代码:

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.

感谢您向我们提出这个问题,但这不是请求错误。 =)

所有7条评论

文件“X/http/client.py”

你写X是因为这是本地文件的路径吗? 如果是这样,您的目录结构可能会混淆 urllib3。 如果没有,那么您可能应该在 bugs.python.org 上提出这个问题,因为我认为请求不应该处理。 这看起来像是从httplib (或者我猜你正在使用的 Python 3 上的http上升。

@西格玛病毒24

我在sublime插件中使用了requests,如果下面语句中的soap_body不包含任何中文字符,也不会有例外。

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

首先,除非您使用的 Sublime Apex 版本与其公共存储库中的版本不同,否则 Requests _不是_最新版本,它是 1.2.3 版。 你能告诉我你使用的是什么版本的 Sublime Text 吗?

这是崇高的文字 3056

所以,ST 3,但不是最新的修订版。 好的,这给了我们一些东西。 具体来说,Sublime Text 3 使用 Python 3.3,而不是 Python 2.7(Sublime Text 2 使用的)。 这意味着 Sublime Apex 中的所有默认字符串都是 unicode 字符串。

如果打开 Python 3.3 http.client文件,您会发现_send_request()函数如下所示:

# 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 是 Latin-1 的别名,这是我们遇到问题的编解码器。 我们遇到的问题是 Sublime Apex 为请求提供了一个 unicode 字符串主体,httplib 需要将其编码为字节。 使用 RFC 2616 中的默认值,它得出结论您需要 Latin-1,其中不包含任何中文字符。 很明显,编码失败,你会得到有问题的异常。

考虑到 Sublime Apex 在其发送的标头中声称要发送 UTF-8 编码数据(目前这是谎言),Sublime Apex 希望在发送数据之前将数据编码为 UTF-8。 这意味着任何发送数据的行(在本例中为salesforce/api.py 545 行)应如下所示:

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

为了其他想要确认我的诊断的人,这里有一小段可以确认问题的示例代码:

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.

感谢您向我们提出这个问题,但这不是请求错误。 =)

谢谢。

r = requests.post(' http://httpbin.org/post ', data=a.encode('utf-8'))
非常有用,
谢谢你!

此页面是否有帮助?
0 / 5 - 0 等级