requests 不能发送 bytearray 数据
import requests
body = b"abc"
body = bytearray(body)
r = requests.post('https://example.com', data=body)
# r = requests.post('https://example.com', data=memoryview(body))
print(r.status_code)
TypeError Traceback (most recent call last)
~/.pyenv/versions/3.7.0/Python.framework/Versions/3.7/lib/python3.7/http/client.py in send(self, data)
976 try:
--> 977 self.sock.sendall(data)
978 except TypeError:
~/.pyenv/versions/3.7.0/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/contrib/pyopenssl.py in sendall(self, data)
330 while total_sent < len(data):
--> 331 sent = self._send_until_done(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE])
332 total_sent += sent
~/.pyenv/versions/3.7.0/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/contrib/pyopenssl.py in _send_until_done(self, data)
319 try:
--> 320 return self.connection.send(data)
321 except OpenSSL.SSL.WantWriteError:
~/.pyenv/versions/3.7.0/Python.framework/Versions/3.7/lib/python3.7/site-packages/OpenSSL/SSL.py in send(self, buf, flags)
1731 if not isinstance(buf, bytes):
-> 1732 raise TypeError("data must be a memoryview, buffer or byte string")
1733 if len(buf) > 2147483647:
TypeError: data must be a memoryview, buffer or byte string
很正常的请求,但是请求的内容不能是 bytearray
,有的电脑可以提交 bytearray
类型数据,
网上的帖子都说是 pyopenssl
的问题,虽然到最后也不知道是什么问题。
异常说提交的内容必须是 memoryview, buffer or byte string
,将提交的内容更改为 ``memoryview`。
memoryview
可变的字节序列,python3
中 str
默认是 unicode
编码,只能通过 bytearray
才能按字节访问。
str
和 bytearray
的切片操作会产生新的切片 str
和 bytearray
并拷贝数据,使用 memoryview
之后不会。
In [72]: stra = bytearray(b'abcde')
In [73]: strb = stra[:3]
In [74]: stra
Out[74]: bytearray(b'abcde')
In [75]: strb
Out[75]: bytearray(b'abc')
In [91]: a = bytearray(b'aaaa') # 创建字节数组
In [92]: b = memoryview(a) # 创建内存视图
In [93]: b.readonly # 可写的内存视图
Out[93]: False
In [94]: c = b[:2] # 不会产生新的 bytearray
In [95]: c
Out[95]: <memory at 0x125fca048>
In [97]: c[:2] = b'ww' # 直接对b数据的修改
In [98]: c.tobytes()
Out[98]: b'ww'
In [99]: b.tobytes()
Out[99]: b'wwaa'
In [100]: a = b'aaaa'
In [101]: b = memoryview(a)
In [102]: b.readonly # 只能读
Out[102]: True
使用 memoryview
可避免大的 str
进行分段解析时的大量切片操作。