在下面的示例中,pickle
每次尝试将实例A保存到文件时都会崩溃。
为什么会发生?
如何避免?
如何绕过它?
class Base(dict):
def __init__(self):
super(Base, self).__init__()
class ClassA(Base):
def __init__(self):
super(ClassA, self).__init__()
def setInstB(self, instB):
self['instB']=instB
class ClassB(Base):
def __init__(self):
super(ClassB, self).__init__()
def setInstA(self, instA):
self['instA']=instA
instA=ClassA()
instB=ClassB()
instA.setInstB(instB)
instB.setInstA(instA)
import pickle
pickle.dump( instA, open( "save.p", "wb" ) )
发布。
如果Base(dict)
类没有声明为内置dict
的子类,问题就消失了。运行下面发布的代码不会引发pickle
错误。但是我仍然想知道为什么pickle失败,以及如何使它与继承dict
的类一起工作。
class Base(object):
def __init__(self):
super(Base, self).__init__()
class ClassA(Base):
def __init__(self):
super(ClassA, self).__init__()
def setInstB(self, instB):
self.instB=instB
class ClassB(Base):
def __init__(self):
super(ClassB, self).__init__()
def setInstA(self, instA):
self.instA=instA
instA=ClassA()
instB=ClassB()
instA.setInstB(instB)
instB.setInstA(instA)
import pickle
pickle.dump( instA, open( "save.p", "wb" ) )
我想你可能遇到了什么问题。我建议你提交它,也许它会得到修复。
下面的代码可以解决你的问题:
# -*- coding: utf-8 -*-
class Base(dict):
def __init__(self):
super(Base, self).__init__()
pk = None
class ClassA(Base):
def __init__(self):
super(ClassA, self).__init__()
def setInstB(self, instB):
self['instB']=instB
class ClassB(Base):
def __init__(self):
super(ClassB, self).__init__()
def setInstA(self, instA):
self['instA']=instA
instA=ClassA()
instA.pk=1
instB=ClassB()
instB.pk=2
instA.setInstB(instB)
instB.setInstA(instA)
import pickle
class MyPickler(pickle.Pickler):
def persistent_id(self, obj):
return obj.pk
MyPickler(open( "save.p", "wb" )).dump(instA)
Pickler允许显式地为您的对象生成unqie id:参见persistent_id
方法,因为这些是数据库对象,我想生成id将很容易。
这可能不是pickle
中的错误,因为我可以pickle
您最初想要做的事情而不会出现问题。如果您使用dill
而不是pickle
,那么就没有问题了……所有dill
都是一堆copy_reg
函数,用于注册如何序列化pickle
默认无法处理的不同类型。
dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class Base(dict):
... def __init__(self):
... super(Base, self).__init__()
...
>>> class ClassA(Base):
... def __init__(self):
... super(ClassA, self).__init__()
... def setInstB(self, instB):
... self['instB']=instB
...
>>> class ClassB(Base):
... def __init__(self):
... super(ClassB, self).__init__()
... def setInstA(self, instA):
... self['instA']=instA
...
>>> instA=ClassA()
>>> instB=ClassB()
>>>
>>> instA.setInstB(instB)
>>> instB.setInstA(instA)
>>>
>>> import dill as pickle
>>> pickle.dump( instA, open('save.p', 'wb') )
>>> res = pickle.load( open('save.p', 'rb') )
>>> res
{'instB': {'instA': {...}}}
>>> res['instB']
{'instA': {'instB': {...}}}
在这里获取dill
:https://github.com/uqfoundation