python:带有二进制数据的 HTTP PUT
因此,我按照另一个问题的答案的建议改编了 urllib2:
class HttpRequest(urllib2.Request):
def __init__(self, *args, **kwargs):
self._method = kwargs.pop('method', 'GET')
urllib2.Request.__init__(self, *args, **kwargs)
def get_method(self):
return self._method
它对于使用 JSON 的 PUT 效果很好:
req = HttpRequest(url=url, method='PUT',
data=json.dumps(metadata))
response = urllib2.urlopen(req)
但它因 data=
二进制数据而失败(下面是部分堆栈跟踪):
File "c:\appl\python\2.7.2\lib\urllib2.py", line 126, in urlopen
return _opener.open(url, data, timeout)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 394, in open
response = self._open(req, data)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 412, in _open
'_open', req)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 372, in _call_chain
result = func(*args)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 1199, in http_open
return self.do_open(httplib.HTTPConnection, req)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 1168, in do_open
h.request(req.get_method(), req.get_selector(), req.data, headers)
File "c:\appl\python\2.7.2\lib\httplib.py", line 955, in request
self._send_request(method, url, body, headers)
File "c:\appl\python\2.7.2\lib\httplib.py", line 989, in _send_request
self.endheaders(body)
File "c:\appl\python\2.7.2\lib\httplib.py", line 951, in endheaders
self._send_output(message_body)
File "c:\appl\python\2.7.2\lib\httplib.py", line 809, in _send_output
msg += message_body
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 10: ordinal
not in range(128)
有没有办法解决这个问题?
So I adapted urllib2 as suggested by answers to another question:
class HttpRequest(urllib2.Request):
def __init__(self, *args, **kwargs):
self._method = kwargs.pop('method', 'GET')
urllib2.Request.__init__(self, *args, **kwargs)
def get_method(self):
return self._method
and it works nicely for PUT with JSON:
req = HttpRequest(url=url, method='PUT',
data=json.dumps(metadata))
response = urllib2.urlopen(req)
but it fails with data=
binary data (partial stacktrace below):
File "c:\appl\python\2.7.2\lib\urllib2.py", line 126, in urlopen
return _opener.open(url, data, timeout)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 394, in open
response = self._open(req, data)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 412, in _open
'_open', req)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 372, in _call_chain
result = func(*args)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 1199, in http_open
return self.do_open(httplib.HTTPConnection, req)
File "c:\appl\python\2.7.2\lib\urllib2.py", line 1168, in do_open
h.request(req.get_method(), req.get_selector(), req.data, headers)
File "c:\appl\python\2.7.2\lib\httplib.py", line 955, in request
self._send_request(method, url, body, headers)
File "c:\appl\python\2.7.2\lib\httplib.py", line 989, in _send_request
self.endheaders(body)
File "c:\appl\python\2.7.2\lib\httplib.py", line 951, in endheaders
self._send_output(message_body)
File "c:\appl\python\2.7.2\lib\httplib.py", line 809, in _send_output
msg += message_body
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 10: ordinal
not in range(128)
Is there a way I can fix this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是因为
来自 urllib2 文档
It's because
from urllib2 doc
您正在尝试自动将 python unicode 字符串转换为常规字节字符串。 JSoN 始终是 unicode,但 HTTP 必须发送字节。如果您确信接收方能够理解特定编码中的 json 编码数据,您可以这样编码:
注意
.encode('utf-8')
,它将转换unicode
到 utf-8 中的str
。隐式转换将使用 ascii,它无法对非 ascii 字符进行编码。tl;dr
... data=json.dumps(blabla).encode('utf-8') ...
You are trying to automatically convert a python unicode string to a regular byte string. JSoN is always unicode, but HTTP must send bytes. If you are confident that the reciever will understand the json encoded data in a particular encoding, you can just encode it that way:
Note the
.encode('utf-8')
, which convertsunicode
tostr
in utf-8. The implicit conversion would use ascii, which cant encode non-ascii characters.tl;dr
... data=json.dumps(blabla).encode('utf-8') ...
根据 urllib2 文档,您需要对字节进行百分比编码-细绳。
According to the urllib2 documentation, you will need to percent-encode the byte-string.