泡菜不';t在Python2.6上不考虑我注册的自定义类型reduce函数
给定以下代码:泡菜不';t在Python2.6上不考虑我注册的自定义类型reduce函数,python,pickle,python-2.6,Python,Pickle,Python 2.6,给定以下代码: 导入pickle 导入副本 A类(类型): 通过 B类(对象): __元类\uuua=A def _reduce_a(a): 打印('嘿,那里') 返回一个名称__ 复制\u reg.pickle(A,\u reduce\u A) 泡菜倾倒区(B) 在Python2.6上尝试pickleB时,注册的\u reduce\u a函数从未被调用,后者是a实例,但在2.7上被调用 这是一个已知的错误吗?我认为这是一个2.6错误/限制。您可以看到,如果调用copy.copy(B),您的函
导入pickle
导入副本
A类(类型):
通过
B类(对象):
__元类\uuua=A
def _reduce_a(a):
打印('嘿,那里')
返回一个名称__
复制\u reg.pickle(A,\u reduce\u A)
泡菜倾倒区(B)
在Python2.6上尝试pickleB
时,注册的\u reduce\u a
函数从未被调用,后者是a
实例,但在2.7上被调用
这是一个已知的错误吗?我认为这是一个2.6错误/限制。您可以看到,如果调用
copy.copy(B)
,您的函数将被调用,但当调用pickle.dumps(B)
时,函数不会被调用。Python 2.7.3中添加了一个新特性,允许动态创建类被pickle。见:
目前,即使用户通过copy_reg请求不同的pickle机制,也不可能使用常用的pickle机制来pickle动态创建的类。附加的补丁通过简单地转置两块代码就可以实现这种定制
及
copy_reg模块用于处理对象的自定义酸洗,这正是此处需要的。但是,检查元类实例的代码在查看copy_reg dispatch表之前执行此操作。修补程序只是在pickle.py和cPickle.c中对这些测试重新排序,这样就可以为元类的实例注册自定义pickler
从以下方面:
问题#7689:当动态创建的类的元类注册到copy#u reg时,允许对其进行酸洗。Nicolas M.Thiéry和Craig Citro的补丁
Python2.6解决这个问题的唯一方法是将pickle.py
模块移植到该版本。您可以尝试将2.7.3pickle.py
模块与2.6捆绑在一起,作为一个纯Python实现,它应该可以正常工作
或者,对pickle.Pickler.save
方法进行猴子补丁:
from copy_reg import dispatch_table
from types import TypeType, StringType, TupleType
from pickle import Pickler, PicklingError
def pickler_save(self, obj):
# Check for persistent id (defined by a subclass)
pid = self.persistent_id(obj)
if pid:
self.save_pers(pid)
return
# Check the memo
x = self.memo.get(id(obj))
if x:
self.write(self.get(x[0]))
return
# Check the type dispatch table
t = type(obj)
f = self.dispatch.get(t)
if f:
f(self, obj) # Call unbound method with explicit self
return
# Check copy_reg.dispatch_table
reduce = dispatch_table.get(t)
if reduce:
rv = reduce(obj)
else:
# Check for a class with a custom metaclass; treat as regular class
try:
issc = issubclass(t, TypeType)
except TypeError: # t is not a class (old Boost; see SF #502085)
issc = 0
if issc:
self.save_global(obj)
return
# Check for a __reduce_ex__ method, fall back to __reduce__
reduce = getattr(obj, "__reduce_ex__", None)
if reduce:
rv = reduce(self.proto)
else:
reduce = getattr(obj, "__reduce__", None)
if reduce:
rv = reduce()
else:
raise PicklingError("Can't pickle %r object: %r" %
(t.__name__, obj))
# Check for string returned by reduce(), meaning "save as global"
if type(rv) is StringType:
self.save_global(obj, rv)
return
# Assert that reduce() returned a tuple
if type(rv) is not TupleType:
raise PicklingError("%s must return string or tuple" % reduce)
# Assert that it returned an appropriately sized tuple
l = len(rv)
if not (2 <= l <= 5):
raise PicklingError("Tuple returned by %s must have "
"two to five elements" % reduce)
# Save the reduce() output and finally memoize the object
self.save_reduce(obj=obj, *rv)
Pickler.save = pickler_save
这是在Python2.6还是2.7上?标签上写着2.6,你的问题上写着2.7。我已经更新了我的问题。
\u reduce\u a
函数在2.7中被调用,但在2.6中没有调用。您知道公开pickle/unpickle函数的其他方法吗?我试着在a
上声明\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,但从未调用过。
>>> pickle.dumps(B)
Hey there
'c__main__\nB\np0\n.'