【问题标题】:How to append chunks of a pickled pandas DataFrame如何附加腌制熊猫数据框的块
【发布时间】:2019-01-17 08:46:39
【问题描述】:

我在我的服务器上腌制了一个 pandas 数据帧,我通过套接字连接发送它,我可以接收数据,但我似乎无法将数据块一起附加回原始数据帧格式,仅此而已我正在努力实现!我有一种感觉,因为 data = [],它变成了一个列表,但我尝试了一个空的 pd Dataframe 并且没有用,所以我有点迷失了如何附加这些价值观

    data = []
    FATPACKET = 0
    bytelength = self.s.recv(BUFFERSIZE)
    length = int(pickle.loads(bytelength))
    print(length)
    ammo = 0

    while True:
        print("Getting Data....")
        packet = self.s.recv(1100)
        FATPACKET = int(sys.getsizeof(packet))
        ammo += FATPACKET
        print(str(FATPACKET) + '  Got this much of data out of '   +str(length))
        print("Getting Data.....")
        data.append(packet)
        print(ammo)
        if not ammo > length:
            break
    print(data)
    unpickled = pickle.loads(data)
    self.s.close()
    print("Closing Connection!")
    print(unpickled)

当我尝试这段代码时,我经常遇到这个

TypeError: 需要一个类似字节的对象,而不是“列表”

或者我遇到了这个

_pickle.UnpicklingError: 无效的加载键,'\x00'

这是我腌制数据框的前几个数字对不起这是我第一次搞乱腌制模块所以我不是很了解

【问题讨论】:

  • pickle.loads 需要一个 bytes 对象。但是你有一个字节对象块的列表。先b''.join(data)

标签: python-3.x pandas sockets pickle


【解决方案1】:

如果我们也能准确地看到您在发送端所做的事情,那将会很有帮助。但是,很明显您有几个问题。

首先,在最初的recv 中,很明显您打算只获取用于编码剩余字节长度的初始pickle 对象。但是,recv 可能 还会收到剩余字节的初始段(或者甚至 所有 剩余字节,具体取决于它的大小)。那么你应该给最初的pickle.loads 多少呢?

您最好创建一个固定长度的字段来包含剩余数据的大小。这通常通过struct 模块完成。在发送方:

import struct
# Pickle the data to be sent
data = pickle.dumps(python_obj)
data_len = len(data)
# Pack data length into 4 bytes, encoded in network byte order
data_len_to_send = struct.pack('!I', data_len)  
# Send exactly 4 bytes (due to 'I'), then send data
conn.sendall(data_len_to_send)
conn.sendall(data)

在接收端,正如异常所说,pickle.loads 接受一个字节字符串而不是一个列表。所以解决这个问题的一部分是在调用loads之前将所有列表元素连接成一个字节字符串:

unpickled = pickle.loads(b''.join(data))

接收方的其他问题:使用len(packet) 获取缓冲区大小。 sys.getsizeof 提供 bytes 对象使用的内部内存,其中包括未指定的解释器开销,这不是您需要的。

recv 之后,您应该做的第一件事是检查指示流结束的空缓冲区(len(packet) == 0packet == ''not packet 甚至)。例如,如果发件人在完成发送之前被杀死(或者网络链接断开,或者发件人端的一些错误等),就会发生这种情况。否则,如果连接提前结束,您的程序将永远无法到达break,因此它将处于非常紧密的无限循环中。

所以,你完全可以这样做:

# First, obtain fixed-size content length
buf = b''
while len(buf) < 4:
    tbuf = recv(4 - len(buf))
    if tbuf == '':
        raise RuntimeError("Lost connection with peer") 
    buf += tbuf

# Decode (unpack) length (note that unpack returns an array)
len_to_recv = struct.unpack('!I', buf)[0]

data = []
len_recved = 0
while len_recvd < len_to_recv:
    buf = self.s.recv(min(len_to_recv - len_recvd, BUFFERSIZE))
    if buf == '':   
        raise RuntimeError("Lost connection with peer") 
    data.append(buf)
    len_recvd += len(buf)

unpickled_obj = pickle.loads(b''.join(data))

编辑:移动括号

【讨论】:

  • 感谢他们的帮助!但是我尝试实现您的代码但是我在 buf = self.s.recv(min(len_to_recv - len_recvd), BUFFERSIZE) 行遇到类型错误它返回一个类型错误,说明 int 对象不可迭代?也非常感谢你告诉我 sys.getsizeof 不是正确使用的东西,当数字一直较小时,我以为我快疯了!
  • 我所做的只是删除了 (min(Len_to_recv - Len_recvd)),因为我不仅真的不知道它的含义,而且它抛出了那个错误,我只是运行了代码,它就这样工作了非常感谢!!!
  • 是的。对不起。括号放错地方了。这就是当您输入代码而不尝试它时会发生的情况。这个想法是你不想接收超过你腌制对象的剩余大小,所以它试图:“接收剩余的数据或 BUFFERSIZE,以较小者为准”。
  • 顺便说一句,如果这解决了你的问题,你应该接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-20
  • 2020-11-25
  • 2018-02-08
  • 2017-06-13
  • 2014-01-03
  • 1970-01-01
相关资源
最近更新 更多