Jas*_*n S 10 python binary http put
我不能为我的生活弄清楚如何使用标准Python库在Python 2.7中使用逐字二进制数据执行HTTP PUT请求.
我以为我可以用urllib2来做,但是因为期望它的格式数据而失败urllib2.Request了application/x-www-form-urlencoded.我不想对二进制数据进行编码,我只想在包含的标题之后逐字传输
Content-Type: application/octet-stream
Content-Length: (whatever my binary data length is)
Run Code Online (Sandbox Code Playgroud)
这看起来很简单,但我仍然围成一圈,似乎无法弄清楚如何.
我怎样才能做到这一点?(除了打开原始二进制套接字并写入它)
Jas*_*n S 12
我发现了我的问题.似乎在urllib2.Request/中存在一些模糊的行为urllib2.urlopen()(至少在Python 2.7中)
该urllib2.Request(url, data, headers)构造似乎期待同类型在其URL和数据参数字符串.
我从文件read()调用中提供了数据参数原始数据(在Python 2.7中以'普通'字符串的形式返回它),但我的url是偶然的Unicode,因为我从另一个函数的结果中连接了一部分URL返回Unicode字符串.
url它试图将data参数"upcast" 为Unicode,而不是试图从Unicode - >普通字符串"向下转换" ,它给了我一个编解码器错误.(奇怪的是,这发生在urllib2.urlopen()函数调用上,而不是urllib2.Request构造函数)
当我改变我的函数调用
# headers contains `{'Content-Type': 'application/octet-stream'}`
r = urllib2.Request(url.encode('utf-8'), data, headers)
Run Code Online (Sandbox Code Playgroud)
它工作得很好.
您误读了文档:urllib2.Request期望已编码的数据,以及通常表示application/x-www-form-urlencoded格式的POST .您可以自由地关联任何其他二进制数据,如下所示:
import urllib2
data = b'binary-data'
r = urllib2.Request('http://example.net/put', data,
{'Content-Type': 'application/octet-stream'})
r.get_method = lambda: 'PUT'
urllib2.urlopen(r)
Run Code Online (Sandbox Code Playgroud)
这将产生您想要的请求:
PUT /put HTTP/1.1
Accept-Encoding: identity
Content-Length: 11
Host: example.net
Content-Type: application/octet-stream
Connection: close
User-Agent: Python-urllib/2.7
binary-data
Run Code Online (Sandbox Code Playgroud)