Python:使用`copyreg`为已有 reducers 的类型定义 reducers

5 投票
1 回答
775 浏览
提问于 2025-04-15 23:18

(请注意,我是在使用Python 3,所以解决方案需要适用于Python 3。)

我想用copyreg模块来教Python如何处理函数的序列化,也就是把函数保存成可以存储的格式。当我尝试这样做时,_Pickler对象仍然会用save_global函数来处理函数的序列化。(这个方法对未绑定的方法不起作用,这也是我想这么做的原因。)

看起来_Pickler会先在自己的dispatch中查找你想序列化的对象类型,然后再去copyreg.dispatch_table中查找。我不确定这是故意的还是怎样。

有没有办法让我告诉Python用我提供的处理器来序列化函数呢?

1 个回答

1

下面这个小技巧在Python 3.1中似乎有效……:

import copyreg
def functionpickler(f):
  print('pickling', f.__name__)
  return f.__name__

ft = type(functionpickler)
copyreg.pickle(ft, functionpickler)

import pickle
pickle.Pickler = pickle._Pickler
del pickle.Pickler.dispatch[ft]

s = pickle.dumps(functionpickler)
print('Result is', s)

从中可以看到,这两行小技巧是:

pickle.Pickler = pickle._Pickler
del pickle.Pickler.dispatch[ft]

你需要去掉函数类型的dispatch条目,因为如果不去掉,它会干扰到copyreg的注册。而且我觉得你不能在用C语言写的Pickler上做到这一点,所以你需要使用用Python写的那个。

如果你自己创建一个类来继承_Pickler,并自己定义一个dispatch(复制父类的并去掉函数类型的条目),这样做会稍微少一点黑科技的感觉。然后你可以专门使用你的子类(和它的dump方法),而不是直接用pickle.dump;不过这样做会比直接修改pickle本身稍微麻烦一点。

撰写回答