重用Python Bytearray / Memoryview

时间:2014-04-03 04:20:59

标签: python python-2.7 python-3.x

我试图通过套接字接收一系列的protobufs;我不会提前知道数据量。我发送了相当数量的这些,并且在收到它们时需要buffer the messages(以确保我收到所有消息)。我想利用Python中可用的bytearray / memoryview来消除不必要的副本。

我正在使用字符串并在收到数据时附加数据。这很容易,我可以通过做类似的事情“转移”到“缓冲区”:

# Create the buffer
str_buffer = []

# Get some data and add it to our "buffer"
str_buffer += "Hello World"

# Do something with the data . . .

# "shift"/offset the message by the data we processed
str_buffer = str_buffer[6:]

使用bytearray / memoryview可以做类似的事吗?

# Create the buffer/memoryarray 
buffer = bytearray(1024)
view   = memoryview(buffer)

# I can set a single byte
view[0] = 'a'

# I can "offset" the view by the data we processed, but doing this 
# shrinks the view by 3 bytes. Doing this multiple times eventually shrinks
# the view to 0.
view = view[3:]

当我尝试添加更多数据时,问题就出现了。如果我“偏移”现有视图,视图的大小“缩小*”,我可以添加越来越少的数据。有没有重用现有的内存视图,只是将数据移到左边?

*根据文档,我知道我无法调整阵列的大小。我认为缩小的幻觉是我的误解。

1 个答案:

答案 0 :(得分:3)

你真的,老实说,不需要事先知道预期会有多少数据,只要继续阅读,直到你不再获得更多数据:

import socket, sys

HOST = 'localhost'        # The remote host
PORT = 50007              # The same port as used by the server

recvbuff = bytearray(16)
recvview = memoryview(recvbuff)

size = 0

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
    nbytes = s.recv_into(recvview)
    if not nbytes:
        break
    size += nbytes
    recvview = recvview[nbytes:]
    if not len(recvview):
        print "filled a chunk", recvbuff
        recvview = memoryview(recvbuff)

print 'end of data', recvbuff[:len(recvview)], size

s.close()