Как правильно реализовать мультипоточность?

Здравствуйте.
Есть небольшой парсер сайтов, необходимо заставить его работать быстрее.
Структура:
# блок с импортами
import ....

# блок с подключением к БД (оттуда нужно забрать урлы по которым пройтись)
conn = sqlite3.connect('db.sqlite3')
curs = conn.cursor()
select = curs.execute("SELECT url from test;")

# блок с основной функцией, которая забирает данные с сайта
def scrape(link):
    ....
    # блок записи в БД, используя подключение выше
    return "Success"

# блок, который вызывает функцию scrape для каждого элемента, что был взят из БД
for link in select.fetchall():
    scrape(link)


Пытался добавить мультипоточность(к сожалению безуспешно), используя модуль - threading
И данный код:
thread_list = []

t = threading.Thread(target=scrape, args=(link,))
thread_list.append(t)

for thread in thread_list:
	thread.start()

for thread in thread_list:
    thread.join()
  • Вопрос задан
  • 1742 просмотра
Пригласить эксперта
Ответы на вопрос 4
Bahusss
@Bahusss
Python Master
Предлагаю вам свой вариант, через очередь задач:

from Queue import Queue
from threading import Thread

def scrape(link):
    conn = sqlite3.connect('db.sqlite3')
    curs = conn.cursor()
    # insert link, close connection

class Worker(Thread):

    def __init__(self, tasks):
        super(Worker, self).__init__()
        self.tasks = tasks
        self.daemon = True

    def run(self):
        while True:
            link = self.tasks.get()
            try:
                scrape(link)
            finally:
                self.tasks.task_done()


if __name__ == '__main__':
    # максимальное количество одновременных потоков
    capacity = 0  # infinite
    queue = Queue(capacity)

    workers = 3
    for _ in range(workers):
        Worker(queue).start()

    for link in select.fetchall():
        queue.put(link)

    queue.join()
    print 'Done'
Ответ написан
@lega
Для парсера сайтов лучше использовать асинхронный фреймворк, пример www.py-my.ru/post/4f278211bbddbd0322000000
Ответ написан
angru
@angru
Как посоветовали выше - используйте какой-нибудь асинхронный фреймворк(мне в свое время понравился gevent). Вам и так и так надо вносить изменения, будь то потоки или асинхронность, а асинхронность на мой взгляд лучше подходит в этом случае, т.к у вас в основном IO-операции, к тому же весь питоновский код все равно выполняется на одном ядре(гуглить GIL) да и SQLite не может потоки, так что не уверен, что потоки дадут вам какие-то преимущества.
Ответ написан
sim3x
@sim3x
sqlite3 файловая однопоточная СУБД. Не стоит ее использовать в многопоточном режиме

Для парсинга используй scrapy

Если сильно хочется самому все написать, то stackoverflow.com/a/6125654
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы