У меня есть сценарий Python, который я хотел бы запускать каждый день, и я бы предпочел, чтобы его работала всего 1-2 часа. В настоящее время он настроен на использование 4 различных API-интерфейсов для заданного URL-адреса, получения результатов и сохранения данных в базе данных PostgreSQL. Проблема в том, что у меня более 160 000 URL-адресов, и сценарий заканчивается очень долго - я провел некоторые предварительные тесты, и для каждого URL в его текущем формате потребуется более 36 часов. Итак, мой вопрос сводится к: следует ли оптимизировать мой скрипт для одновременного запуска нескольких потоков? Или я должен масштабировать количество серверов, которые я использую? Очевидно, что второй подход будет более дорогостоящим, поэтому я бы предпочел, чтобы в одном экземпляре выполнялось несколько потоков.Улучшить скорость скрипта Python: многопоточность или несколько экземпляров?
Я использую созданную мной библиотеку (SocialAnalytics), которая предоставляет методы для ударов по различным конечным точкам API и анализа результатов. Вот как я мой сценарий конфигурации:
import psycopg2
from socialanalytics import pinterest
from socialanalytics import facebook
from socialanalytics import twitter
from socialanalytics import google_plus
from time import strftime, sleep
conn = psycopg2.connect("dbname='***' user='***' host='***' password='***'")
cur = conn.cursor()
# Select all URLs
cur.execute("SELECT * FROM urls;")
urls = cur.fetchall()
for url in urls:
# Pinterest
try:
p = pinterest.getPins(url[2])
except:
p = { 'pin_count': 0 }
# Facebook
try:
f = facebook.getObject(url[2])
except:
f = { 'comment_count': 0, 'like_count': 0, 'share_count': 0 }
# Twitter
try:
t = twitter.getShares(url[2])
except:
t = { 'share_count': 0 }
# Google
try:
g = google_plus.getPlusOnes(url[2])
except:
g = { 'plus_count': 0 }
# Save results
try:
now = strftime("%Y-%m-%d %H:%M:%S")
cur.execute("INSERT INTO social_stats (fetched_at, pinterest_pins, facebook_likes, facebook_shares, facebook_comments, twitter_shares, google_plus_ones) VALUES(%s, %s, %s, %s, %s, %s, %s, %s);", (now, p['pin_count'], f['like_count'], f['share_count'], f['comment_count'], t['share_count'], g['plus_count']))
conn.commit()
except:
conn.rollback()
Вы можете видеть, что каждый вызов API использует Requests library, который является синхронным, блокируя дело. После некоторых предварительных исследований я обнаружил Treq, который является API поверх Twisted. Асинхронный, неблокирующий характер Twisted кажется хорошим кандидатом для улучшения моего подхода, но я никогда не работал с ним, и я не уверен, как именно (и если) это поможет мне достичь моей цели.
Любое руководство очень ценится!
Требуется ли для разных запросов URL-адрес разделяемое пространство памяти? В противном случае простым решением будет использование многопроцессорности. Для некоторого быстрого кода см. Http://stackoverflow.com/questions/3842237/parallel-processing-in-python – duhaime
Нет, им не требуется разделяемое пространство памяти. Единственный способ, я могу думать о том, чтобы избавиться от необходимого количества времени, - это запустить 10 процессов, каждый из которых будет обрабатывать собственный URL. Однако я не совсем уверен, как это сделать. С этим подходом я направляюсь в правильном направлении? https://gist.github.com/anonymous/b337afbd8f92d3991b47 – Abundnce10
Извините, просто получил это. Кажется, все сработало :) – duhaime