要讲memoryview,就要讲它的主要应用场合—-缓冲区(buffer)
要讲buffer前就要讲讲Python的字符处理:Python中的字符是不能修改的 例如
当你需要收集从socket.recv上来的代码时,大部分的人都选择了拼接字符串
while not self.sock.closed:
data = ''
while len(data) < 1024:
d = self.sock.recv(12)
if not d: return;
data += d
殊不知,由于Python字符串的特点,这实际上是将data复制一份,然后于d进行拼接,然后再赋值给data。
当字符大小有1M左右的时候,这种复制的效率会下降10%左右(其他大小没有测试过,但是应该是字符越大,复制的效率就越低,毕竟要重新分配内存区域并填满是很费事的)
而且网络传输有个特点,就是客户端想传多大都可以,所以就会出现只传输部分数据的情况,这时,socket.recv循环次数增多,导致字符缓冲区复制的操作次数增多。
所以,对于已知缓冲区大小下,可以先分配大小的缓冲区,然后依次写入相应数据即可(不需要复制了)。 改装上面的栗子,我们假定已知缓冲区应该有1KB
buf = bytearray(1024)
mv = memoryview(buf)
i = 0
while i < 1024:
i = self.sock.recv_into(mv)
if not i: return; # remote closed
if i < 1024:
mv = mv[i:1024]
i += i
即可