Моя задача - загрузить 1M + изображения из заданного списка URL-адресов. Каков рекомендуемый способ сделать это?Загрузка изображений с gevent
После того, как я прочитал Greenlet Vs. Threads Я просмотрел gevent
, но я не могу надежно его запустить. Я играл с тестовым набором из 100 URL-адресов, и иногда он заканчивается в 1,5 секунды, но иногда это занимает более 30 секунд, что странно, поскольку таймаут * для каждого запроса равен 0,1, поэтому он никогда не должен принимать более 10 секунд.
* смотрите ниже в коде
Я также посмотрел в grequests
, но они, кажется, issues with exception handling.
Мои «требования» являются, что я могу
- проанализировать ошибки, возникающих при загрузке (таймауты , поврежденные изображения ...),
- отслеживает ход обработки обработанных изображений и
- быть как можно быстрее.
from gevent import monkey; monkey.patch_all()
from time import time
import requests
from PIL import Image
import cStringIO
import gevent.hub
POOL_SIZE = 300
def download_image_wrapper(task):
return download_image(task[0], task[1])
def download_image(image_url, download_path):
raw_binary_request = requests.get(image_url, timeout=0.1).content
image = Image.open(cStringIO.StringIO(raw_binary_request))
image.save(download_path)
def download_images_gevent_spawn(list_of_image_urls, base_folder):
download_paths = ['/'.join([base_folder, url.split('/')[-1]])
for url in list_of_image_urls]
parameters = [[image_url, download_path] for image_url, download_path in
zip(list_of_image_urls, download_paths)]
tasks = [gevent.spawn(download_image_wrapper, parameter_tuple) for parameter_tuple in parameters]
for task in tasks:
try:
task.get()
except Exception:
print 'x',
continue
print '.',
test_urls = # list of 100 urls
t1 = time()
download_images_gevent_spawn(test_urls, 'download_temp')
print time() - t1
Нужно ли использовать темы? Если вы можете использовать несколько процессов, вы можете сделать это с помощью 'multiprocessing.Pool', и вы можете найти его проще. Я использую 'pool.map (download_image, url_list)' и 'pool.join()', чтобы сделать что-то подобное. – foz
@foz, спасибо, но я также попробовал «multiprocessing.Pool» с аналогичными проблемами. Также мне сказали, что «многопроцессорство» не является подходящим инструментом для таких задач: http://stackoverflow.com/a/27016937/380038 – Framester
Интересно! Я вижу, что многопроцессорность не так эффективна/масштабируема, но я не понимаю, почему она не должна работать со скромным размером пула (32, как и у вас). Надеюсь, вы получите хороший ответ на это, я думаю, что я тоже кое-что узнаю! – foz