在编码流中读写pickle

1 投票
1 回答
663 浏览
提问于 2025-04-15 23:30

我们系统中常用的一种文件格式是经过 base64 编码的 pickle 文件。现在,我可以用一些简单的代码将这种简单格式的字符串进行转换,代码如下:

def dumps( objinput ):
    """
    Return an encoded cPickle
    """
    return cpickle_dumps( objinput ).encode( ENCODING )

def loads( strinput ):
    """
    Return an object from an encoded cpickle
    """
    return cpickle_loads( strinput.decode( ENCODING ) )

我想实现一个新的功能,叫做“load”,它的工作方式和标准的 pickle load 函数很像,只不过它会从一个数据流中读取足够的字节,然后返回解码后的对象。这里的关键是要读取足够的字节——cPickle.load 函数就是这样做的,它会从数据流中逐个取出字节,直到获取到完整的 pickle 数据。我的新函数需要像这样:

def load( stream_input ):
    """"
    Return just one object popped from the stream. 
    If the stream has ended, raise an exception
    Do not over-read the stream.

那么,当数据是经过 base64 编码的 pickle 时,我该如何实现呢?这里的难点在于,不太明显是通过包装 cPickle.load 函数还是包装输入流来完成这个任务。另外一个困难是,可能一个字节的 pickle 数据在 base64 编码后会变成多个字节,所以不清楚如何将 stream_input.read(n) 转换成一个可以确保返回 n 字节解码数据的方式,因为输入流是经过 base64 编码的。

1 个回答

1

我觉得你可以通过实现一个类似文件的对象来做到这一点,这样就可以直接传给cPickle.load。

class Base64PickleAdapter:
  def __init__(self, base64_input):
    ...

  def read(size=-1):
    ...   

  def readline():
    ... # Can be implemented in terms of read.

cPickle只需要你实现读取和逐行读取这两个功能。你不需要在Base64PickleAdapter.read中返回固定大小的字节。根据read的规定,你可以返回更少的数据,这样可以让实现变得简单一些。

撰写回答