#python #multiprocessing
Вопрос:
Похоже, что apply_async не работает, и ничего не происходит. Не знаю, что здесь не так. Я использую macOS catalina
import time from multiprocessing import Pool def worker(sl): print(sl) time.sleep(sl) return sl if __name__ == '__main__': with Pool(processes=3) as pool: for i in range(5,30,5): result = pool.apply_async(func=worker,args=(i,))
Комментарии:
1. какую среду разработки вы используете? не все IDE правильно обрабатывают инструкции печати из дочерних процессов. Spyder, например, только что улучшил поддержку в 5.2.0, вы также перезаписываете
result
и сохраняете только последнюю…2. Я использую версию кода Visual Studio: 1.61.2
3. попробуйте запустить свой код с терминала (или cmd в Windows).
4. Я бы также рекомендовал обновить python по крайней мере до 3.9, если вы действительно хотите начать использовать
multiprocessing
(если ваш проект позволяет это). Начиная с версии 3.6 было выпущено несколько важных обновлений и исправлений
Ответ №1:
Когда вы звоните pool.apply_async
, вы планируете выполнение задачи. Возвращаемое значение этого вызова-это multiprocessing.pool.AsyncResult
экземпляр, для которого вы вызываете метод get
, который будет заблокирован до завершения задачи и вернет возвращаемое значение из рабочей функции, указанной в apply_async
вызове метода. Но вы не звонили get
(или wait
) ни в один из этих AsyncResult
случаев. Вместо этого вы позволили себе немедленно провалиться в конец with Pool(processes=3) as pool:
блока, и в этом заключается ваша проблема.
Документация не очень ясна. Однако есть такое предупреждение:
Внимание:
multiprocessing.pool
у объектов есть внутренние ресурсы, которыми необходимо правильно управлять (как и любым другим ресурсом), используя пул в качестве контекстного менеджера или вызываяclose()
иterminate()
вручную. Невыполнение этого требования может привести к зависанию процесса доработки.
Вы используете пул в качестве контекстного менеджера в результате выполнения with
инструкции, и на самом деле происходит то, что при завершении with
блока происходит вызов pool.terminate()
. Таким образом, все процессы в пуле немедленно завершаются до того, как у них появится возможность выполнить любую из представленных вами задач.
Поскольку вас не интересуют фактические возвращаемые значения worker
, альтернативой сохранению AsyncResult
объектов и вызову get
их является вызов pool.close()
, за которым следует pool.join()
перед выходом из with
блока, который будет ждать завершения всех отправленных задач.:
close()
Предотвращает отправку в пул новых задач. Как только все задачи будут выполнены, рабочие процессы завершатся.
join()
Дождитесь завершения рабочих процессов. Необходимо позвонитьclose()
илиterminate()
перед использованиемjoin()
.
import time from multiprocessing import Pool def worker(sl): print(sl) time.sleep(sl) return sl if __name__ == '__main__': with Pool(processes=3) as pool: for i in range(5,30,5): result = pool.apply_async(func=worker,args=(i,)) pool.close() pool.join()
С принтами:
5 10 15 20 25