在这里使用永久性ID解决的酸洗问题是什么?

时间:2019-06-02 12:10:11

标签: python python-3.x pickle

来自https://docs.python.org/3/library/pickle.html#persistence-of-external-objects

  

为受益于对象持久性,pickle模块支持   在腌制数据流之外引用对象的概念。   此类对象由持久ID引用,该ID应该是   一串字母数字字符(用于协议0)或仅   任意对象(用于任何较新的协议)。

如果有人能解释,我将不胜感激:在这里使用永久性ID解决的酸洗问题是什么?换句话说,如果不使用持久性ID,酸洗会出现什么问题?

特别是,“在腌制数据流之外引用对象的概念”是什么意思?它是否与某些其他概念相反,例如“在腌制数据流中引用对象的概念”?

1 个答案:

答案 0 :(得分:1)

“棘手数据流”是“ pickle.dumppickle.load做什么”的通用描述。例如,数据流是一个文件,可以从中顺序读取数据。当该流包含泡菜产生或消耗的数据时,它是一个<腌制数据流。

Pickle流具有内部引用的概念-如果同一对象在流中多次出现,则仅存储一次,然后仅对其进行引用。但是,这仅指流中已存储的内容-引用不能指向流外部的对象,例如原始对象。泡菜数据流的内容从概念上讲是其原始数据的副本。

import pickle

bar = (1, 2)
foo = {1: 1, 2: (1, 1), 'bar': bar}

with open('foo.pkl', 'wb') as out_stream:  # open a data stream...
     pickle.dump((bar, foo), out_stream)   # ...for pickle data

with open('foo.pkl', 'rb') as in_stream:
     bar2, foo2 = pickle.load(in_stream)

assert bar2 is foo2['bar']  # internal identity is preserved
assert bar is not bar2      # external identity is broken

持久性ID可用于引用流中未包含的内容,例如原始对象或全局数据库句柄,或另一个流中的内容或类似内容。从概念上讲,持久性ID仅允许其他代码处理酸洗/酸洗。但是,持久性ID的定义和实现取决于要解决的问题。

定义和使用永久性ID并不困难。但是,这需要进行一些编排和簿记。一个非常简单的示例如下所示:

import io
import pickle

# some object to persist
# usually, one would have some store or bookkeeping in place
bar = (1, 2)

# the create/load implementation of the persistent id
def persistent_bar_id(obj):
    """Return a persistent id for the `bar` object only"""
    return "it's a bar" if obj is bar else None

def persistent_bar_load(pers_id):
    if pers_id == "it's a bar":
       return bar
    raise pickle.UnpicklingError(
        "This is just an example for one persistent object!")

stream = io.BytesIO()  # in-memory stream for demonstration
# need to extend Pickler and Unpickler with the persistent id handlers
pickler = pickle.Pickler(stream)
pickler.persistent_id = persistent_bar_id
unpickler = pickle.Unpickler(stream)
unpickler.persistent_load = persistent_bar_load

# we can now dump and load the persistent object
pickler.dump({'bar': bar})
stream.seek(0)
foo = unpickler.load()
assert foo['bar'] is bar  # persistent identity is preserved

作为一个真实的例子,我的旧cpy2py module使用pickle在不同的解释器之间交换数据。对于常规的类似值的对象,这意味着在一个解释器中进行序列化,而在另一个解释器中进行反序列化。对于某些特殊的有状态对象,这意味着只能在所有连接的解释器之间交换唯一标识该对象的永久性ID。

涉及一些簿记,但是在这种情况下,您可以将persistent ID视为元组(process_id, object_id, object_type)。拥有的解释器可以使用此ID查找实际对象,而其他解释器可以代替地创建占位符对象。在这种情况下,最重要的是状态不会被存储和复制,而只是被引用。