动态特征不能在酸洗中生存

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

上一篇: Dynamic traits do not survive pickling

下一篇: Keep getting Error: redirect