【问题标题】:Creating a variable that can be compared across processes创建可以跨流程进行比较的变量
【发布时间】:2011-11-02 11:44:50
【问题描述】:

我有如下代码,

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)它确实有效。尽管这不是一个合适的解决方案,因为这些值中的任何一个都可能在队列中有效。

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

(注意,我也尝试过使用专用类,但收到关于无法腌制的错误。)

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

【问题讨论】:

    标签: python process python-3.x multiprocessing


    【解决方案1】:

    这是使用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,“在模块顶层定义的类”可以腌制。

    【讨论】:

    • 谢谢,我只是以Event 为例。就像我说的那样,Manager 返回的任何对象都会发生这种情况,如果它有效,我可能会在一天结束时使用Value(不太确定为什么我没有在示例中使用!)。感谢关于使用类的建议,我应该提到,我已经尝试过了,并得到一个关于类不能被腌制的错误。我已经更新了问题以提及这一点。
    • 如果您直接将 type 放入队列中,例如q.put(StopProcessing),然后用if dat is StopProcessing进行测试?根据pickle doc,“在模块顶层定义的类”可以腌制。
    • 啊!我试过只添加类型,是的。事实上,这是我在搞乱Manager 对象之前尝试的第一件事,但我总是将类作为内部类。将其纳入模块范围使其完美运行。非常感谢你。我想知道您是否可以将该提示添加到您的答案中以匹配我在问题中的更新。
    猜你喜欢
    • 2013-03-14
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    相关资源
    最近更新 更多