multiprocessing.Pool
уже имеет общую очередь результатов, нет необходимости дополнительно задействовать Manager.Queue
. Manager.Queue
представляет собой queue.Queue
(многопоточную очередь) под капотом, расположенную на отдельном серверном процессе и доступную через прокси. Это добавляет дополнительные накладные расходы по сравнению с внутренней очередью Pool. В отличие от использования встроенной обработки результатов Pool, порядок результатов в Manager.Queue
также не гарантируется.
Рабочие процессы не запускаются .apply_async()
, это уже происходит при создании экземпляра Pool
. Что это началось , когда вы звоните pool.apply_async()
новая «работа». Рабочие процессы пула запускают multiprocessing.pool.worker
функцию под капотом. Эта функция заботится об обработке новых «задач», передаваемых через внутренний пул, Pool._inqueue
и об отправке результатов обратно родительскому объекту через Pool._outqueue
. Указанное func
вами будет выполнено в пределах multiprocessing.pool.worker
. func
нужно только return
что-то, и результат будет автоматически отправлен обратно родителю.
.apply_async()
немедленно (асинхронно) возвращает AsyncResult
объект (псевдоним для ApplyResult
). Вам нужно вызвать .get()
(блокирует) этот объект, чтобы получить фактический результат. Другой вариант - зарегистрировать функцию обратного вызова , которая запускается, как только становится готов результат.
from multiprocessing import Pool
def busy_foo(i):
"""Dummy function simulating cpu-bound work."""
for _ in range(int(10e6)):
pass
return i
if __name__ == '__main__':
with Pool(4) as pool:
print(pool._outqueue)
results = [pool.apply_async(busy_foo, (i,)) for i in range(10)]
print(results[0])
results = [res.get() for res in results]
print(f'result: {results}')
Пример вывода:
<multiprocessing.queues.SimpleQueue object at 0x7fa124fd67f0>
<multiprocessing.pool.ApplyResult object at 0x7fa12586da20>
result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Примечание. Указание параметра timeout
-параметра для .get()
не остановит фактическую обработку задачи внутри рабочего процесса, а только разблокирует ожидающего родителя, подняв multiprocessing.TimeoutError
.