Python 2.6 Envie o objeto de conexão sobre fila / tubo / etc
-
22-07-2019 - |
Pergunta
Dado Este bug (edição 4892 do Python) Isso dá origem ao seguinte erro:
>>> 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
Alguém conhece uma solução alternativa para passar um objeto de conexão em uma fila?
Obrigada.
Solução
(O que eu acredito é) um método melhor, depois de alguns brincando (eu estava tendo o mesmo problema. Queria passar um cano através de um cano.) Antes de descobrir este post:
>>> from multiprocessing import Pipe, reduction
>>> i, o = Pipe()
>>> reduced = reduction.reduce_connection(i)
>>> newi = reduced[0](*reduced[1])
>>> newi.send("hi")
>>> o.recv()
'hi'
Não sei ao certo por que isso é construído dessa maneira (alguém precisaria de informações sobre o que diabos a parte de redução do multiprocessamento é para isso), mas definitivamente funciona e não requer importação de picles. Fora isso, está bem próximo do que faz no que faz, mas mais simples. Eu também joguei isso no relatório do Python Bug para que outras pessoas saibam da solução alternativa.
Outras dicas
Aqui está aproximadamente o que eu fiz:
# 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)
e
# 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])
A última linha é enigmática, proveniente do seguinte:
>>> upw
(<function rebuild_connection at 0x1005df140>,
(('/var/folders/.../pymp-VhT3wX/listener-FKMB0W',
17, False), True, True))
Espero que ajude outra pessoa. Isso funciona bem para mim.