【问题标题】:Does Python Pickle have an illegal character/sequence I can use as a separator?Python Pickle 是否有可以用作分隔符的非法字符/序列?
【发布时间】:2010-10-19 22:18:22
【问题描述】:

我想制作(和解码)一个由几个 python 泡菜组成的单个字符串。

是否有一个字符或序列可以安全地用作此字符串中的分隔符?

我应该能够像这样制作字符串:

s = pickle.dumps(o1) + PICKLE_SEPARATOR + pickle.dumps(o2) + PICKLE_SEPARATOR + pickle.dumps(o3) ...

我应该能够获取这个字符串并像这样重建对象:

[pickle.loads(s) for s in input.split(PICKLE_SEPARATOR)]

PICKLE_SEPARATOR 应该是什么?


出于好奇,我想使用 APPEND 将腌制对象发送到 redis。 (虽然也许我只会使用 RPUSH)

【问题讨论】:

  • 既然redis的值可以是字符串的集合,为什么不把每一个单独存储呢?

标签: python pickle


【解决方案1】:

将泡菜串在一起就可以了,Python知道每个泡菜的结束位置

>>> import cStringIO as stringio
>>> import cPickle as pickle
>>> o1 = {}
>>> o2 = []
>>> o3 = ()
>>> p = pickle.dumps(o1)+pickle.dumps(o2)+pickle.dumps(o3)
>>> s = stringio.StringIO(p)
>>> pickle.load(s)
{}
>>> pickle.load(s)
[]
>>> pickle.load(s)
()

【讨论】:

  • 一个潜在的陷阱:这不适用于字符串,仅适用于类似文件的对象:尝试 pickle.load(s) 三次,只返回 dict
【解决方案2】:

编辑:首先考虑 gnibbler 的答案,这显然要简单得多。喜欢下面这个的唯一原因是,如果您希望能够在不解析的情况下拆分一系列泡菜。

一个相当安全的选择是使用一个您永远不会在其他任何地方重复使用的全新 UUID。评估一次uuid.uuid4().bytes 并将结果作为分隔符存储在您的代码中。例如:

>>> import uuid
>>> uuid.uuid4().bytes
'\xae\x9fW\xff\x19cG\x0c\xb1\xe1\x1aV%P\xb7\xa8'

然后将生成的字符串文字复制粘贴到您的代码中作为分隔符(如果您愿意,甚至可以使用上面的分隔符)。几乎可以保证,相同的序列永远不会出现在您想要存储的任何内容中。

【讨论】:

    【解决方案3】:

    我不怎么使用 Python,但是你有什么理由不能只腌制一个数组吗?于是酸洗就变成了

    s = pickle.dumps([o1,o2,o3])
    

    重建就变成了

    objs = pickle.loads(s)
    

    编辑1:另外,根据this answer,腌制输出是自终止的;因此,你可以腌制

    s = ''.join(map(pickle.dumps,[o1,o2,o3]))
    

    并恢复

    import StringIO
    sio = StringIO.StringIO(s)
    objs = []
    try:
        while True: objs.append(pickle.load(sio))
    catch EOFError:
        pass
    

    不过,我不确定这样做有什么好处。 (虽然我没有看到,但可能有比那个讨厌的循环/异常组合更好的方法;就像我说的,我不怎么使用 Python。)

    【讨论】:

    • 不幸的是,这不适用于流。我需要单独阅读字符串,因为我不能使用泡菜load,而只能使用loads
    【解决方案4】:

    在 Python 3 中可以使用 BytesIO 来完成:

    from io import BytesIO
    import pickle
    
    o1 = {}
    o2 = []
    o3 = ()
    p = pickle.dumps(o1) + pickle.dumps(o2) + pickle.dumps(o3)
    s = BytesIO(p)
    
    while True:
        try:
            print(pickle.load(s))
        except EOFError:
            break
    

    打印:

    {} 
    []
    ()
    

    回答原来的问题。没有简单的方法来分离连接的腌制对象。但幸运的是,您不必这样做。 pickle.load 将在每次连续调用时一个接一个地返回对象。

    【讨论】:

      【解决方案5】:

      一种解决方案是在你的泡菜字符串前面加上每个组成元素包含多少个字符的数据。

      【讨论】:

        猜你喜欢
        • 2018-07-31
        • 2013-06-23
        • 1970-01-01
        • 2011-01-20
        • 2010-10-25
        • 2021-12-01
        • 1970-01-01
        • 2012-02-28
        • 1970-01-01
        相关资源
        最近更新 更多