动态特征不能在酸洗中生存
traits_pickle_problem.py
from traits.api import HasTraits, List
import cPickle
class Client(HasTraits):
data = List
class Person(object):
def __init__(self):
self.client = Client()
# dynamic handler
self.client.on_trait_event(self.report,'data_items')
def report(self,obj,name,old,new):
print 'client added-- ' , new.added
if __name__ == '__main__':
p = Person()
p.client.data = [1,2,3]
p.client.data.append(10)
cPickle.dump(p,open('testTraits.pkl','wb'))
上面的代码报告了一个动态的特征。 这段代码中的一切都按预期工作。 但是,使用新的 python进程并执行以下操作:
>>> from traits_pickle_problem import Person, Client
>>> p=cPickle.load(open('testTraits.pkl','rb'))
>>> p.client.data.append(1000)
导致没有附加列表的报告 。 但是,重新建立听众分开如下:
>>> p.client.on_trait_event(p.report,'data_items')
>>> p.client.data.append(1000)
client added-- [1000]
使其重新工作。
我是否缺少某些东西,或者在__setstate__
处理过程中__setstate__
需要在__setstate__
中重新建立处理程序。
任何帮助赞赏。 这是针对特性版本4.30的Windows 2.7(32位)。
运行pickletools.dis(cPickle.dumps(p))
,你可以看到被引用的处理程序对象:
...
213: c GLOBAL 'traits.trait_handlers TraitListObject'
...
但没有关于如何连接到report
方法的进一步信息。 因此,trait_handler不会自动将其自身排除,或者它是一个临时文件,就像文件句柄一样,不能在第一时间进行清理。
无论哪种情况,最好的选择是重载__setstate__
并在重新创建对象时重新连线事件处理程序。 这并不理想,但至少一切都包含在对象中。
class Person(object):
def __init__(self):
self.client = Client()
# dynamic handler
self.client.on_trait_event(self.report, 'data_items')
def __setstate__(self, d):
self.client = d['client']
self.client.on_trait_event(self.report, 'data_items')
def report(self, obj, name, old, new):
print 'client added-- ', new.added
取消文件现在正确地注册事件处理程序:
p=cPickle.load(open('testTraits.pkl','rb'))
p.client.data.append(1000)
>>> client added-- [1000]
您可能会发现Alex Gaynor在PyCon上做的这个演讲很有趣。 它进入了酸洗工作的最高点。
编辑 - 使用on_trait_change
初始响应 - 似乎正常工作的错字。 为了清晰起见,将其更改回on_trait_event
。
我遇到了同样的问题,但出现这种情况:成像我只想腌一个安静的大班的一部分,一些对象已设置为瞬态=真,所以它们不被腌制,因为没有什么重要的保存,例如
class LineSpectrum(HasTraits):
andor_cam = Instance(ANDORiKonM, transient=True)
与应该保存的对象不同,例如
spectrometer = Instance(SomeNiceSpectrometer)
在我的LineSpectrum类中,我有一个
def __init__(self, f):
super(LineSpectrum, self).__init__()
self.load_spectrum(f)
def __setstate__(self, state): # FUCKING WORKING!
print("LineSpectrum: __setstate__ with super(...) call")
self.__dict__.update(state)
super(LineSpectrum, self).__init__() # this has to be done, otherwise pickled sliders won't work, also first update __dict__!
self.from_pickle = True # is not needed by traits, need it for myself
self.andor_cam = ANDORiKonM(self.filename)
self.load_spectrum(self.filename)
在我的情况下,这是完美的 - 所有的滑块都在工作,在对象被腌制时设置的所有值都被设置回来。
希望这适用于你或任何有同样问题的人。 得到了Anaconda Python 2.7.11,所有软件包都已更新。
PS:我知道线程已经老了,但不想为此打开一个新线程。
链接地址: http://www.djcxy.com/p/19853.html