В зависимости от того, как я поместил объект Queue (сгенерированный с помощью Manager) внутри другого объекта Queue (также сгенерированного через менеджер), я получаю другое поведение, если делаю то же самое, насколько я понимаю.
Вот минимальный рабочий пример:
Код: Выделить всё
import multiprocessing
import Queue
def work(inbound_queue, keep_going):
while keep_going.value == 1:
try:
outbound_queue = inbound_queue.get(False) # this fails in case 3
#do some work
outbound_queue.put("work done!")
except Queue.Empty:
pass #this is busy wait of course, it's just an example
class Weird:
def __init__(self):
self.manager = multiprocessing.Manager()
self.queue = self.manager.Queue()
self.keep_going = multiprocessing.Value("i", 1)
self.worker = multiprocessing.Process(target = work, args = (self.queue, self.keep_going))
self.worker.start()
def stop(self): #close and join the second process
self.keep_going.value = 0
self.worker.join()
def queueFromOutside(self, q):
self.queue.put(q)
return q
def queueFromNewManager(self):
q = multiprocessing.Manager().Queue()
self.queue.put(q)
return q
def queueFromOwnManager(self):
q = self.manager.Queue()
self.queue.put(q)
return q
if __name__ == '__main__':
instance = Weird()
# CASE 1
queue = multiprocessing.Manager().Queue()
q1 = instance.queueFromOutside(queue) # Works fine
print "1: ", q1.get()
# CASE 2
q2 = instance.queueFromNewManager() # Works fine
print "2: ", q2.get()
# CASE 3
q3 = instance.queueFromOwnManager() # Error
print "3: ", q3.get()
instance.stop() #sadly never called :(
ВЫВОД для основного:
Код: Выделить всё
1: work done!
2: work done!
3:
ВЫВОД для рабочего процесса:
Код: Выделить всё
Process Process-2:
Traceback (most recent call last):
File "C:\Python27\lib\multiprocessing\process.py", line 258, in _bootstrap
self.run()
File "C:\Python27\lib\multiprocessing\process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "J:\Dropbox\Python\queues2.py", line 7, in work
outbound_queue = inbound_queue.get(False) # this fails in case 3
File "", line 2, in get
File "C:\Python27\lib\multiprocessing\managers.py", line 774, in _callmethod
raise convert_to_error(kind, result)
RemoteError:
---------------------------------------------------------------------------
Unserializable message: ('#RETURN', )
---------------------------------------------------------------------------
Приведенный пример не похож на структуру кода в реальном проекте, но я отправляю очереди запущенным процессам, и все работает нормально, если я делаю это с помощью методов №1 и №2. Однако было бы неплохо использовать метод №3, поскольку он избавляет от необходимости каждый раз получать менеджер, что может занять удивительно много времени (~ 100 мс на машине, на которой я сейчас работаю).
Вопрос возникает из любопытства, поскольку я все еще изучаю все интересные вещи в модуле многопроцессорности.
ОБНОВЛЕНИЕ, пытаюсь прояснить вопрос: в случае 3 (
Код: Выделить всё
queueFromOwnManagerОБНОВЛЕНИЕ 2: сделало пример более похожим на то, что я на самом деле делаю в коде
Подробнее здесь: https://stackoverflow.com/questions/333 ... processing