Не знаю, почему никто не упоминает multiprocessing
(если кто-нибудь знает, почему это может быть плохой идеей, дайте мне знать):
import multiprocessing
from urllib2 import urlopen
URLS = [....]
def get_content(url):
return urlopen(url).read()
pool = multiprocessing.Pool(processes=8) # play with ``processes`` for best results
results = pool.map(get_content, URLS) # This line blocks, look at map_async
# for non-blocking map() call
pool.close() # the process pool no longer accepts new tasks
pool.join() # join the processes: this blocks until all URLs are processed
for result in results:
# do something
Есть несколько предостережений с multiprocessing
бассейнами. Во-первых, в отличие от потоков, это совершенно новые процессы Python (интерпретатор). Хотя он не подлежит глобальной блокировке интерпретатора, это означает, что вы ограничены в том, что вы можете передать новому процессу.
Вы не можете передавать лямбды и функции, которые определены динамически. Функция, используемая в вызове map()
, должна быть определена в вашем модуле так, чтобы другой процесс мог импортировать ее.
Pool.map()
, который является наиболее простым способом одновременной обработки нескольких задач, не позволяет передавать несколько аргументов, поэтому вам может потребоваться написать функции-оболочки или изменить сигнатуры функций и / или передать несколько аргументов как часть итерируемого, который отображается.
У вас не может быть дочерних процессов, порождающих новые. Только родитель может порождать дочерние процессы. Это означает, что вам нужно тщательно планировать и тестировать (а иногда и писать несколько версий кода), чтобы определить, как наиболее эффективно использовать процессы.
Несмотря на недостатки, я считаю, что многопроцессорная обработка является одним из наиболее простых способов одновременного блокирования вызовов. Вы также можете комбинировать многопроцессорность и потоки (агаик, но, пожалуйста, исправьте меня, если я ошибаюсь), или комбинировать многопроцессорность с зелеными нитями.