在多处理中放置multiprocessing.Queue.Queue会爆炸

时间:2013-04-25 11:36:19

标签: python multithreading queue multiprocessing

以下代码抛出异常并在python 2.7和3.3中打印123。

from multiprocessing import Queue

class Pool(object):
    def __init__(self):
        self.q = Queue()

p = Pool()
p.q.put(p)
print(123)

这实际上是某种竞争条件,如下所示:

yuv@yuvpad2:~/$ python3.3 t.py
123
Traceback (most recent call last):
  File "/home/yuv/Downloads/Python-3.3.0/Lib/multiprocessing/queues.py", line 249, in _feed
yuv@yuvpad2:~/$ 

完整错误为RuntimeError: Queue objects should only be shared between processes through inheritance,并且回溯根本不解释它发生的方式/位置。问题的根源是队列中的对象无法引用队列。我的真实用例实际上是一个工作对象和一个池对象,工作人员将其报告完成了工作池的Queue。所以我希望工人将自己送回工作人员Queue

我没有使用Queue.Queue的原因,虽然多线程对我的情况很有效,但是因为在Python 2.7中有一个错误使得queue.get()忽略了Ctrl-C,这只是烦人的。 / p>

有没有办法干净地做这个模式?

The real problem code is on codepad

3 个答案:

答案 0 :(得分:0)

我想有几种方法可以做到这一点,但是如果不确切知道它是什么,你就不要去做它很难推荐一个。

我想最简单的就是为此目的使用2个不同的队列。一个用于新来的工人,一个用于成品工人。

答案 1 :(得分:0)

回溯未在代码中显示问题的原因是multiprocessing.Queue类启动后台线程,并且在该线程中生成异常。我得到以下追溯......

Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/queues.py", line 266, in _feed
    send(obj)
  File "/usr/lib/python2.7/multiprocessing/queues.py", line 77, in __getstate__
    assert_spawning(self)
  File "/usr/lib/python2.7/multiprocessing/forking.py", line 51, in assert_spawning
    ' through inheritance' % type(self).__name__
RuntimeError: Queue objects should only be shared between processes through inheritance

......我怀疑是由线路发起的......

p.q.put(p)

...您似乎将Pool对象包含Queue对象放入Queue,这是不允许的,因此错误。

如果你想要一个有用的解决方案,那将有助于澄清你想要实现的目标。

答案 2 :(得分:0)

抱怨的错误是:

p.q.put(p)

在这里,您尝试将引用Queue的对象放入队列中。队列用于在进程之间进行通信,其工作方式是将您尝试放入其中的任何内容进行腌制,然后在另一个进程中对其进行取消 - 但是不可能腌制Queue,甚至不能感。

这就是为什么当你尝试挑选一个队列时,你会得到你提到的错误:

>>> from multiprocessing import Queue
>>> q = Queue()
>>> import pickle
>>> pickle.dumps(q)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.2/multiprocessing/queues.py", line 77, in __getstate__
    assert_spawning(self)
  File "/usr/lib/python3.2/multiprocessing/forking.py", line 51, in assert_spawning
    ' through inheritance' % type(self).__name__
RuntimeError: Queue objects should only be shared between processes through inheritance

如果要使用队列在进程之间共享数据,可以这样做:

class Worker(multiprocessing.Process):
    queue = multiprocessing.Queue()
    def run(self):
        print(self.queue.get())
        ...

有关更多示例,请查看docs