问题在于
MyBus对象的某些部分不可腌制,并且您正在将实例保存
MyBus到
Broker实例中。由于Windows缺乏
fork()支持,因此在调用时
broker.start(),
broker必须在
multiprocessing产生的子进程中对的整个状态进行酸洗并重新创建
broker.run。它可以在Linux上运行,因为Linux支持
fork。在这种情况下,它不需要腌制任何东西-
子进程在分叉后立即包含父级的完整状态。
解决此问题的方法有两种。第一种也是更困难的方法是使您的
broker实例可腌制。为此,您需要将其变为可
MyBus腌制的。您现在遇到的错误是指上的
logger属性
MyBus,该属性不可腌制。这个很容易解决;只需向中添加
__getstate__/
__setstate__方法
MyBus,即可控制如何对对象进行酸洗/酸洗。如果我们在腌制时删除记录器,而在腌制时重新创建它,则可以解决此问题:
class MyBus(wspbus.Bus): ... def __getstate__(self): self_dict = self.__dict__ del self_dict['logger'] return self_dict def __setstate__(self, d): self.__dict__.update(d) self.open_logger()
这可行,但是然后我们遇到 另一个 酸洗错误:
Traceback (most recent call last): File "async2.py", line 121, in <module> broker.start() File "C:python34libmultiprocessingprocess.py", line 105, in start self._popen = self._Popen(self) File "C:python34libmultiprocessingcontext.py", line 212, in _Popen return _default_context.get_context().Process._Popen(process_obj) File "C:python34libmultiprocessingcontext.py", line 313, in _Popen return Popen(process_obj) File "C:python34libmultiprocessingpopen_spawn_win32.py", line 66, in __init__ reduction.dump(process_obj, to_child) File "C:python34libmultiprocessingreduction.py", line 60, in dump ForkingPickler(file, protocol).dump(obj)_pickle.PicklingError: Can't pickle <class 'cherrypy.process.wspbus._StateEnum.State'>: attribute lookup State on cherrypy.process.wspbus failed
结果是
cherrypy.process.wspbus._StateEnum.State,它是
wspbus.Bus继承的类的属性
MyBus,是一个嵌套类,不能对嵌套类进行腌制:
class _StateEnum(object): class State(object): name = None def __repr__(self): return "states.%s" % self.name
该
State对象(惊喜)用于跟踪
Bus实例的状态。由于在启动总线之前要进行酸洗,所以我们可以在酸洗
state时从对象中删除属性,然后在酸洗时将其设置为States.STOPPED。
class MyBus(wspbus.Bus): def __init__(self, name=""): wspbus.Bus.__init__(self) self.open_logger(name) self.subscribe("log", self._log) def __getstate__(self): self_dict = self.__dict__ del self_dict['logger'] del self_dict['state'] return self_dict def __setstate__(self, d): self.__dict__.update(d) self.open_logger() self.state = wspbus.states.STOPPED # Initialize to STOPPED
通过这些更改,代码可以按预期工作!唯一的限制是,只有
MyBus在总线尚未启动的情况下,才可以安全地进行腌制,这对于您的用例来说是很好的。
同样,这是困难的方法。最简单的方法是完全消除对
MyBus实例进行酸洗的需要。您可以
MyBus在子进程中创建实例,而不是在父进程中创建实例:
class Broker(Process): def __init__(self, queue): Process.__init__(self) self.queue = queue... def run(self): self.bus = MyBus(Broker.__name__) # Create the instance here, in the child self.bus.subscribe("main", self.check) self.bus.start() self.bus.block(interval=0.01)
只要您不需要
broker.bus在父级中访问,这就是更简单的选择。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)