Python – странное поведение с очередями, менеджерами и многопроцессорностьюPython

Программы на Python
Anonymous
Python – странное поведение с очередями, менеджерами и многопроцессорностью

Сообщение Anonymous »

Работая над своим любимым проектом, включающим одновременную загрузку с использованием модуля multiprocessing, я столкнулся с любопытным поведением объектов Queue, сгенерированных объектом multiprocessing.Manager().
В зависимости от того, как я поместил объект 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 :(
и его выходные данные (python 2.7.10 x86, windows).
ВЫВОД для основного:

Код: Выделить всё

1:  work done!
2:  work done!
3:
затем рабочий процесс аварийно завершает работу, оставляя q3.get() зависающим.
ВЫВОД для рабочего процесса:

Код: Выделить всё

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', )
---------------------------------------------------------------------------
Итак, вопрос: почему третий случай вызывает RemoteError?
Приведенный пример не похож на структуру кода в реальном проекте, но я отправляю очереди запущенным процессам, и все работает нормально, если я делаю это с помощью методов №1 и №2. Однако было бы неплохо использовать метод №3, поскольку он избавляет от необходимости каждый раз получать менеджер, что может занять удивительно много времени (~ 100 мс на машине, на которой я сейчас работаю).
Вопрос возникает из любопытства, поскольку я все еще изучаю все интересные вещи в модуле многопроцессорности.
ОБНОВЛЕНИЕ, пытаюсь прояснить вопрос: в случае 3 (

Код: Выделить всё

queueFromOwnManager
) почему self.manager.Queue() создает очередь, которая после помещения в self.queue не может быть получена с помощью self.queue.get(), в то время как очередь, созданная с помощью multiprocessing.Manager().Queue(), может быть получена? Порядок выполнения 3-х дел не имеет значения. В идеале экземпляр.queue должен быть пустым до и после любого из трех вызовов методов в трех примерах.
ОБНОВЛЕНИЕ 2: сделало пример более похожим на то, что я на самом деле делаю в коде

Подробнее здесь: https://stackoverflow.com/questions/333 ... processing

Вернуться в «Python»