📜  copyreg — 注册 pickle 支持函数(1)

📅  最后修改于: 2023-12-03 15:30:05.749000             🧑  作者: Mango

copyreg — 注册 pickle 支持函数

copyreg 是 Python 内置模块之一,用于在将对象序列化为 pickle 格式时注册自定义的序列化和反序列化函数。也就是说,如果你想将一个不支持 pickle 序列化的对象序列化为 pickle 格式,则可以使用 copyreg 模块来注册转换函数。本文将详细介绍该模块的使用方式和注意事项。

注册 pickle 支持函数

copyreg 模块提供了三个最基本的函数,它们是:

  • pickle_reducer(func)
  • pickle_constructor(func)
  • pickle_destructor(func)

这三个函数分别用于注册 pickle 的 reduce 函数、构造函数和析构函数。

所谓“reduce 函数”是指将一个对象转换为一个“减少”表示形式的函数,来支持 pickle 序列化。因此,如果你想将一个不支持 pickle 序列化的对象序列化为 pickle 格式,则可以通过编写 reduce 函数,再将其注册到 copyreg 模块中,这样 pickle 序列化的时候就会自动调用该函数。比如下面这个例子:

import copyreg
import pickle

class Foo:
    def __init__(self, a, b):
        self.a = a
        self.b = b

def foo_unpickler(data):
    return Foo(*data)

def foo_pickler(foo):
    return foo_unpickler, (foo.a, foo.b)

copyreg.pickle(Foo, foo_pickler, foo_unpickler)

foo = Foo(1, 2)
data = pickle.dumps(foo)
foo2 = pickle.loads(data)
assert foo.__dict__ == foo2.__dict__
自动注册 pickle 支持函数

除了手动注册 pickle 支持函数外,我们也可以定义一个默认的 pickle 支持函数,并让 copyreg 自动调用。为此,我们只需要在模块的顶层定义两个名为 __reduce__()__reduce_ex__() 的函数即可。这两个函数需要返回一个 tuple,其中第一个元素为一个构造函数,第二个元素为一个 tuple,用来构造该构造函数所需的参数。

import copyreg
import pickle

class Foo:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __reduce__(self):
        return Foo, (self.a, self.b)

foo = Foo(1, 2)
data = pickle.dumps(foo)
foo2 = pickle.loads(data)
assert foo.__dict__ == foo2.__dict__
注意事项
  • 注册的 pickle 支持函数必须能够处理所有该类型的实例对象,而不仅仅是指定实例对象。
  • 如果你想定制化 pickle 的行为,可以自己编写一个类,并定义自己的 __reduce__()__reduce_ex__() 函数。使用 copyreg 注册 pickle 支持函数时,也必须使用返回的 tuple 中的构造函数来创建该对象。
  • pickle 虽然方便,但是不推荐过度使用。如果你需要传输的对象比较大或内部结构比较复杂,建议使用更为标准的数据格式,例如 JSON 或 msgpack 等。