В рамках более глубокого изучения питона решил написать реальный проект - агрегатор блогосферы польского интернета. Проблема появилась в моменте изпользования gevent (http://www.gevent.org) библиотеки для парралельного доступа к удаленному контенту. Ранее я не решал таких задачь и не хочу изобретать свой велосипед. Поэтому решил обратиться за помощью к комьюнити.
Вкратце, схема моей работы выглядит так:
Описание схемы:
У меня есть база данных RSS лент (около 1000) разделенная по категориям. Каждый час нужно проверять их состояние и обрабатывать новые item's в лентах. Обработка заключается в загрузке контента, анализе и поиске картинок для приготовления превью item'a.
Как это происходит в однопоточном режиме (примерный, упрощенный код):
for url, etag, l_mod in rss_urls:
rss_feed = process_rss(url, etag, l_mod) # Read url with last etag, l_mod values
if not rss:
continue
for new_item in rss_feed: # Iterate via *new* items in feed
element = fetch_content(new_item) # Direct https request, download HTML source
if not element:
continue
images = extract_images(element)
goodImages = []
for img in images:
if img_qualify(img): # Download and analyze image if it could be used as a thumbnail
goodImages.append(img)
Т.е. в итоге я делаю http запросы в таких моментах:
- получение рсс документа
- получение item'a из рсс документа
- получение всех картинок рсс документа
Естественно это занимает непростительно много времени даже на моем домашнем интернете т.к. все запросы блокирующие и идут в один поток. Я решил использовать gevent т.к. о нем много хороших отзывов и судя по документации он довольно прост в использовании, как раз для таких задачь.
Чтобы я хотел получить в результате:
- Возможность стабильного ограничения количества исходящих соединений.
- Возможность парралельной загрузки нескольких рсс фидов, парралельного доступа к их новым item'мам и естественно парралельной загрузки картинок каждого item'a.
Как проще/лучше всего этого добиться?
Все что у меня пока есть это идея написать класс который сохраняет в себе количество запущенных задач (и сбрасывает это значение в базу данных с некоторой перидичностью), класс умеет запускать новые задачи и отслеживает событие выполнения какой то задачи. Должен получится некоторый враппер для gevent однако - как приготовить его малой кровью, я пока не знаю и не до конца уверен что такая задача решается именно придуманым способом. Я не хочу сильно (вообще?) менять функции, непосредственно отвественные за вызов удаленного соединения. В идеале думаю правильнее всего должен получится результат, когда системе все равно есть gevent или его нет - если его нет, то все будет запускаться в однопоточном режиме (удобно для тестирования), если же он есть - система будет использовать указанное количество Pool с определенными таймаутами.
Буду рад любым наставническим советам.
Спасибо!