Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 动态特性不能经受酸洗 特性\u pickle\u问题.py_Python_Traits_Pickle - Fatal编程技术网

Python 动态特性不能经受酸洗 特性\u pickle\u问题.py

Python 动态特性不能经受酸洗 特性\u pickle\u问题.py,python,traits,pickle,Python,Traits,Pickle,上面的代码报告了一个动态特性。在这段代码中,一切都按预期工作。但是,使用新的python进程并执行以下操作: >>> from traits_pickle_problem import Person, Client >>> p=cPickle.load(open('testTraits.pkl','rb'))

上面的代码报告了一个动态特性。在这段代码中,一切都按预期工作。但是,使用新的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]     
使它再次工作

在取消勾选过程中,我是否丢失了某些内容,或者是否需要在
\uuuu setstate\uuuu
中重新建立处理程序


谢谢你的帮助。这适用于traits版本为4.30的windows上的Python 2.7(32位)。

运行
pickletools.dis(cPickle.dumps(p))
,您可以看到正在引用的处理程序对象:

  ...
  213: c        GLOBAL     'traits.trait_handlers TraitListObject'
  ...
但是没有关于如何将它连接到
报告
方法的更多信息。因此,要么trait_处理程序本身没有正确地进行pickle处理,要么它是一个短暂的东西,比如一个文件句柄,不能在第一时间进行pickle处理

在这两种情况下,最好的选择是重载
\uuu setstate\uuu
,并在重新创建对象时重新连接事件处理程序。这并不理想,但至少所有内容都包含在对象中

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]
你可能会觉得有趣。它进入了如何在引擎盖下酸洗工作的高点


编辑-在改变特征时使用的初始响应
-一种似乎有效的打字错误。为清晰起见,将其更改回\u trait\u event上的

我也遇到了同样的问题,但结果是这样的:映像我只想pickle一个安静的大类的一部分,并且一些对象被设置为transient=True,因此它们不会被pickle,因为没有什么重要的东西需要保存,例如

class LineSpectrum(HasTraits):
    andor_cam = Instance(ANDORiKonM, transient=True)
与应保存的对象不同,例如

spectrometer = Instance(SomeNiceSpectrometer)
在我的线谱课上,我有一个

def __init__(self, f):
    super(LineSpectrum, self).__init__()
    self.load_spectrum(f)

def __setstate__(self, state):  # 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)
在我的例子中,这是完美的-所有滑块都在工作,对象被pickle时设置的所有值都被设置回原处

希望这对你或任何有同样问题的人有效。获得了Anaconda Python 2.7.11,更新了所有包


PS:我知道线程很旧,但不想为此打开一个新线程。

我查看了hastraits资源,没有找到任何关于它如何存储回调处理程序的有用信息。我太不耐烦了。无论如何,问题似乎不在于代码,而在于特性。我觉得这有点老套,但我认为setstate是个不错的选择。请记住,setstate将实例dict作为参数接收,在重新建立处理程序之前,必须将其分配给self。
def __init__(self, f):
    super(LineSpectrum, self).__init__()
    self.load_spectrum(f)

def __setstate__(self, state):  # 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)