创建可跨流程进行比较的变量

时间:2011-11-02 11:44:50

标签: python process python-3.x multiprocessing

我的代码如下,

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()创建的任何对象都会发生这种情况,但如果我使用“true”单例(TrueFalseNone),则确实有效。虽然这不是一个合适的解决方案,因为这些值中的任何一个都可能在队列中有效。

那么如何创建一个可以跨进程进行比较的变量(如单例)?

(N.B。我也试过使用专门的课程,但是因为它无法被腌制而得到错误。)

更新:答案似乎是使用一个类,但我收到了挑剔的问题,因为我只是尝试使用内部类。将其移动到模块范围可以修复错误并且工作正常。 - 谢谢@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()

1 个答案:

答案 0 :(得分:3)

使用Event对象这是一种奇怪的方式...如果你不能使用None或布尔值,我建议你使用一个专用的类来测试你得到的类型从队列中:

class StopProcessing(object):
    pass

#...

q.put(StopProcessing())

#...

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

或者,当然,您可以继续使用multiprocessing.Event并测试其类型。但是,如果其他人阅读您的代码,这可能会产生误导;使用专用类型对我来说似乎更清洁和Pythonic。

编辑:好的,显然这不起作用,因为新类不可选。所以这是另一个想法:如果直接将类型放入队列中,如下所示:

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

根据pickle doc,“模块顶层定义的类”可以被腌制。