Python 2.6 通过队列/管道等发送连接对象

11 投票
2 回答
3946 浏览
提问于 2025-04-15 14:25

根据这个问题(Python问题4892),它会导致出现以下错误:

>>> import multiprocessing
>>> multiprocessing.allow_connection_pickling()
>>> q = multiprocessing.Queue()
>>> p = multiprocessing.Pipe()
>>> q.put(p)
>>> q.get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File     "/.../python2.6/multiprocessing/queues.py", line 91, in get
    res = self._recv()
TypeError: Required argument 'handle' (pos 1) not found

有没有人知道有什么办法可以在队列中传递一个连接对象?

谢谢。

2 个回答

8

大概我做了以下这些事情:

# Producer
from multiprocessing.reduction import reduce_connection
from multiprocessing import Pipe

   # Producer and Consumer share the Queue we call queue
def handle(queue):
   reader, writer = Pipe()
   pickled_writer = pickle.dumps(reduce_connection(writer))
   queue.put(pickled_writer)

还有

# Consumer
from multiprocessing.reduction import rebuild_connection

def wait_for_request():
    pickled_write = queue.get(block=True) # block=True isn't necessary, of course
    upw = pickle.loads(pickled_writer) # unpickled writer
    writer = upw[0](upw[1][0],upw[1][1],upw[1][2])

最后一行有点难懂,来源于下面这段:

>>> upw
(<function rebuild_connection at 0x1005df140>,
(('/var/folders/.../pymp-VhT3wX/listener-FKMB0W',
17, False), True, True))

希望这能对其他人有所帮助。对我来说运行得很好。

8

我认为这是一个更好的方法,经过一番尝试后(我也遇到了同样的问题,想要在一个管道中通过另一个管道),才发现了这篇帖子:

>>> from multiprocessing import Pipe, reduction
>>> i, o = Pipe()
>>> reduced = reduction.reduce_connection(i)
>>> newi = reduced[0](*reduced[1])
>>> newi.send("hi")
>>> o.recv()
'hi'

我不太确定为什么会这样设计(需要有人了解多进程中的“归约”部分才能解释这个),但确实有效,而且不需要导入pickle。除此之外,它的功能和上面提到的差不多,但更简单。我还把这个方法提交到了python的bug报告中,这样其他人也能知道这个解决办法。

撰写回答