2011-11-02 28 views
2

我有如下代码,创建可以跨进程进行比较的变量

class _Process(multiprocessing.Process): 

    STOP = multiprocessing.Manager().Event() 

    def __init__(self, queue, process_fn): 

     self._q = queue 
     self._p = process_fn 
     super().__init__() 

    def run(self): 

     while True: 
      dat = self._q.get() 
      if not dat is _Process.STOP: 
       self._p(dat, self._q) 
       self._q.task_done() 
      else: 
       self._q.task_done() 
       break 

,但是,我不能比较STOP成功。当我使用is时,这并不奇怪,因为我相信is比较了对象ID和文档“...这是内存中对象的地址。”因此,由于我使用多个进程,内存地址将会不同。 (尽管我无法将它与==进行比较,但我不确定这是为什么)。

这种情况与我Manager()创建的任何对象,但如果我用一个“真实”的单身(TrueFalseNone),它的工作。尽管这不是一个合适的解决方案,因为这些值中的任何值都可能在队列中有效。

那么我怎样才能创建一个变量,像单身人士,可以跨过程进行比较?

(注:我已经使用专用类也尝试过,但得到它不能够进行酸洗错误)

更新:答案似乎是使用一类,但我接受pickleing问题,因为我只是在尝试一个内部类。将它移动到模块范围修复了错误并且工作正常。 - 谢谢@Schnouki!


下面是一个例子(和毫无意义)的代码,显示错误的用法......

def f(data, queue): 
    print(data) 

q = multiprocessing.JoinableQueue() 

for i in range(4): 
    p = _Process(q, f) 
    p.daemon = True 
    p.start() 
    q.put(i) 

q.join() 

for i in range(4): 
    q.put(_Process.STOP) 

q.join() 

回答

3

这是使用Event对象奇怪的是......如果你可以” T选用None或一个布尔值,我建议你使用一个专用的类和测试的类型,你从队列中获取:

class StopProcessing(object): 
    pass 

#... 

q.put(StopProcessing()) 

#... 

while True: 
    dat = self._q.get() 
    if type(dat) is StopProcessing: 
     # ... 

或者,当然了,你可以使用只是不停并测试其类型。然而,这可能会让别人读你的代码时产生误导。使用专用类型似乎对我来说更加清洁和Pythonic。

编辑:好吧,很显然,这是行不通的,因为新的类不可挑选。因此,这里的另一个想法:如果你直接把你的类型里面的队列,像这样:

class StopProcessing(object): 
    pass 
#... 
q.put(StopProcessing) 
#... 
while True: 
    dat = self._q.get() 
    if dat is StopProcessing: 
     #... 

按照pickle doc,“那是在一个模块的顶层定义的类”可以腌制。

+0

谢谢,我刚刚用'Event'作为例子。就像我说的那样,由'Manager'返回的任何对象都会发生,如果它能够工作,我可能会在一天结束时使用'Value'(不确定为什么我没有在这个例子中!)。感谢关于使用类的建议,我应该提到,我已经尝试过了,并且得到关于该类不能被腌制的错误。我已经更新了这个问题。 – tjm

+0

如果您直接在队列中放置* type *,例如'q.put(StopProcessing)',然后用'如果dat是StopProcessing'测试它?根据[pickle doc](http://docs.python.org/py3k/library/pickle.html#what-c​​an-be-pickled-and-unpickled),“在顶层定义的类模块“可以被腌制。 – Schnouki

+0

啊!我已经试过了,只是增加了类型,是的。事实上,这是我尝试的第一件事,之前搞乱了'经理'对象,但我始终把课程作为内部类。将它纳入模块范围使其完美工作。非常感谢你。我想知道是否可以将该提示添加到您的答案中以匹配问题中的更新。 – tjm

相关问题