В приведенном ниже примере кода я хотел бы восстановить возвращаемое значение функции worker
. Как я могу сделать это? Где хранится это значение?
Пример кода:
import multiprocessing
def worker(procnum):
'''worker function'''
print str(procnum) + ' represent!'
return procnum
if __name__ == '__main__':
jobs = []
for i in range(5):
p = multiprocessing.Process(target=worker, args=(i,))
jobs.append(p)
p.start()
for proc in jobs:
proc.join()
print jobs
Вывод:
0 represent!
1 represent!
2 represent!
3 represent!
4 represent!
[<Process(Process-1, stopped)>, <Process(Process-2, stopped)>, <Process(Process-3, stopped)>, <Process(Process-4, stopped)>, <Process(Process-5, stopped)>]
Я не могу найти соответствующий атрибут в объектах, хранящихся в jobs
.
multiprocessing.Queue
, а неManager
здесь. ИспользованиеManager
требует запуска совершенно нового процесса, который излишним, когдаQueue
бы сделал.multiprocessing.Pool.map
для обработки вашего списка рабочих элементов.args=(my_function_argument, )
. Запишите,
здесь запятую! Или же Python будет жаловаться на «отсутствие позиционных аргументов». Мне понадобилось 10 минут, чтобы понять. Также проверьте использование вручную (в разделе «класс процесса»).Я думаю, что подход, предложенный @sega_sai, является лучшим. Но это действительно нуждается в примере кода, так что здесь идет:
Который будет печатать возвращаемые значения:
Если вы знакомы с
map
(встроенным в Python 2), это не должно быть слишком сложным. В противном случае взгляните на ссылку sega_Sai .Обратите внимание, как мало кода требуется. (Также обратите внимание, как процессы используются повторно).
источник
getpid()
возвращение все равно стоит? Я бегу Python3pool.map
диапазон 1 000 000, используя более 10 процессов, я вижу самое большее два разных пида.pool.apply_async
: docs.python.org/3/library/…В этом примере показано, как использовать список экземпляров multiprocessing.Pipe для возврата строк из произвольного числа процессов:
Вывод:
Это решение использует меньше ресурсов, чем многопроцессорное. Вопрос, который использует
или мультипроцессинг. Простая проблема, которая использует
Очень поучительно посмотреть на источник для каждого из этих типов.
источник
Pipe
на процесс против одногоQueue
для всех процессов. Я не знаю, будет ли это более эффективным во всех случаях.По какой-то причине я не смог найти общий пример того, как это сделать
Queue
где угодно (даже примеры документов Python не порождают несколько процессов), поэтому вот что я получил после 10 попыток:Queue
блокирующая потокобезопасная очередь, которую можно использовать для хранения возвращаемых значений дочерних процессов. Таким образом, вы должны передать очередь каждому процессу. Что менее очевидно , является то , что вы должныget()
из очереди перед вамиjoin
вProcess
эс или иначе очередь заполняет и блокирует все.Обновление для тех, кто является объектно-ориентированным (протестировано в Python 3.4):
источник
Для тех, кто ищет, как получить ценность от
Process
использованияQueue
:источник
Queue
из своей функции, это позволит мне пройтиjoin()
queue.put(ret)
до звонкаp.start()
? В этом случае рабочий поток будет зависатьqueue.get()
вечно. Вы можете повторить это, скопировав мой фрагмент выше при комментированииqueue.put(ret)
.queue.get()
должно произойти доp.join()
. Это работает сейчас для меня.Кажется, что вы должны использовать вместо этого класс multiprocessing.Pool и использовать методы .apply () .apply_async (), map ()
http://docs.python.org/library/multiprocessing.html?highlight=pool#multiprocessing.pool.AsyncResult
источник
Вы можете использовать
exit
встроенный, чтобы установить код выхода процесса. Его можно получить изexitcode
атрибута процесса:Вывод:
источник
Пакет pebble имеет хорошее использование абстракции,
multiprocessing.Pipe
что делает его довольно простым:Пример из: https://pythonhosted.org/Pebble/#concurrent-decorators
источник
Думаю, я упростил бы самые простые примеры, скопированные сверху, работая для меня на Py3.6. Самый простой это
multiprocessing.Pool
:Вы можете установить количество процессов в бассейне с, например,
Pool(processes=5)
. Тем не менее, по умолчанию используется счетчик ЦП, поэтому оставьте его пустым для задач, связанных с ЦП. (Задачи с привязкой к вводу / выводу часто все равно подходят потокам, так как потоки в основном ожидают, поэтому могут совместно использовать ядро ЦП.)Pool
Также применяется оптимизация разбиения на блоки .(Обратите внимание, что рабочий метод не может быть вложен в метод. Сначала я определил свой рабочий метод внутри метода, который выполняет вызов
pool.map
, чтобы он оставался автономным, но затем процессы не смогли его импортировать, и выдал «AttributeError». : Не могу выбрать локальный объект external_method..inner_method ". Подробнее здесь . Может быть внутри класса.)(Оцените оригинальный вопрос, заданный печатью,
'represent!'
а неtime.sleep()
, но без него я думал, что некоторый код выполнялся одновременно, когда это не так.)Py3 также
ProcessPoolExecutor
состоит из двух строк (.map
возвращает генератор, поэтому вам нужноlist()
):С простым
Process
es:Используйте,
SimpleQueue
если все, что вам нужно, этоput
иget
. Первый цикл запускает все процессы, прежде чем второй выполняет блокирующиеqueue.get
вызовы. Я не думаю, что есть причина звонитьp.join()
тоже.источник
Простое решение:
Вывод:
источник
Если вы используете Python 3, вы можете использовать
concurrent.futures.ProcessPoolExecutor
в качестве удобной абстракции:Вывод:
источник
Я немного изменил ответ vartec, так как мне нужно было получить коды ошибок из функции. (Спасибо Vertec !!! это удивительный трюк)
Это также может быть сделано с помощью,
manager.list
но я думаю, что лучше иметь это в dict и хранить список в нем. Таким образом, мы сохраняем функцию и результаты, поскольку не можем быть уверены в том, в каком порядке будет заполняться список.источник