Python и SEO

Пул потоков. Модуль Threading.

Я думаю,  пример из SEO-софта на тему пула потоков долго искать не придется. Взять тот же Хрумер. Указал количество потоков, например 20, запустил – все 20 работают, как только один из них завершит работу – запускается следующий и так, пока не закончатся ссылки. Наверное в 9 из 10 случаев я пишу скрипт с использованием пула потоков.  Рассмотрим некторые примеры.

Пример 1. «В лоб».

    threads = []
    for x in range(THREADS):
        new_thread = threading.Thread(target=step_one)
        threads.append(new_thread)
        new_thread.start()
        time.sleep(1)
    while True: # какое-то условие
        for y in threads[:]:
            if not y.isAlive():
                threads.remove(y)
                new_thread = threading.Thread(target=step_one)
                threads.append(new_thread)
                new_thread.start()
        time.sleep(0.1)
    while threading.activeCount()>0:
        time.sleep(5)

Функцию step_one запускаем в несколько потоков, все созданные потоки храним в списке. Затем провереяем в цикле какие потоки завершили работу и, если такие есть, создаем новые и так, пока не достигнем какого-либо результата. Криво, неудобно, зато сразу понятно. Достаточно долго пользовался такой реализацией, а всё из-за лени.

Пример 2. Семафоры.

import time
import threading
max_potokov = 20
maxconnections = 5
akkiQueue = threading.BoundedSemaphore(value=maxconnections)

def doform():
    akkiQueue.acquire()
    # код функции
    akkiQueue.release()

for i in xrange(max_potokov):
    time.sleep(1)
    p = threading.Thread(target=doform)
    p.setDaemon(True)
    p.start()
while threading.activeCount()>0:
    time.sleep(5)

Уже лучше, количество потоков контролируется, но надо заранее знать сколько будет потоков, в общем как-то изворачиваться если тебе надо будет прервать все эти потоки по условию.

Пример 3. Очереди.

queue = Queue.Queue() # создаем очередь

def register(item):
    #Функция с основным кодом
    return
def repeat():
    while True:
        try:
            item = queue.get_nowait() # ждём данные
        except Queue.Empty:
            break
        register(item) # передаем данные в нашу функцию
        time.sleep(0.5)
        queue.task_done() # задача завершена
for item in range(MAX_THREADS):
    queue.put(item) # заносим данные в очередь
for i in xrange(THREADS):
    t = threading.Thread(target=repeat) # создаем нить
    t.start() # стартуем
    time.sleep(0.5)
queue.join() # блокируем очередь до завершения

Здесь используется модуль Queue. На данный для меня самый удобный варинат – и выглядит красиво, и данные передавать можно.

Помимо тех вариантов, что я описал, можно погуглить на тему threadpool и найти какие-нибудь модули для организации пула потоков.

 

Автор: kalombo

Октябрь 6, 2009 в 9:32 пп

Категория Python

Метки , threading, питон, семафор

Ответы: 9 to 'Пул потоков. Модуль Threading.'

Подписаться на комментарии RSS or TrackBack to 'Пул потоков. Модуль Threading.'.

  1. О! Я нашёл таки человека со схожими интересами.
    Тоже юзаю сео и тоже юзаю питон ))

    Щас вот сооружаю скриптец на тему автопостинга неких ссылок, получаемых с некоего сервера, в некий фрихостовый хост с пузами )
    Точнее, несколько фрихостовых хостов =)

    Подумал, что было бы круто сразу получать ссыли с сервака и в этом же время получать код поста с фрихоста для сравнения с кодом ссылок.

    Вот и пошёл гулять по просторам преимущественно рунета, дабы освоить многопоточность в Пайтоне.

    Бум дружить?
    ЗЫ. Подписываюсь на тебя
    ЗЗЫ. У меня в ЖЖ стоят ссыли верхним постом. Там может оказаться и порно всякое и прочее – не пугайся. Монетизируюсь )
    ЗЗЗЫ. Ася моя, если чо – 7622763

    Крайст

    11 Янв 10 at 17:44

  2. Да без проблем, давай дружить, контакты я тож указал если что. Своим сообщением ты мотивировал меня на новый пост, ушел делать=)

    kalombo

    11 Янв 10 at 20:00

  3. А между потоком и основной частью программы возможно взаимодействие?
    Т.е. поток, отсылает данные о своих действиях – завершен на 65%, регаю, логинюсь и тп

    Alex Volkov

    22 Янв 10 at 00:41

  4. Дак просто:
    print «Регистрируюсь»
    в функции, которая запускается отдельным потоком.
    Можно вообще не блокировать очередь в 3м примере, убрав строчку queue.join() и продолжать что-то делать в главном потоке, только за остальными надо будет уже следить вручную.

    kalombo

    22 Янв 10 at 01:19

  5. А засуспендить\возобновить поток получится? Отдельно от других потоков, то есть 10 работают а один ждет?

    P.S. Поставь еще плз плуг для извещения об ответах на мыло, а то не очень удобно блог постоянно открытым держать

    Alex Volkov

    22 Янв 10 at 01:25

  6. Да можно наверняка. Глянь тут http://docs.python.org/library/threading.html, не приходилось мне суспендить.

    kalombo

    22 Янв 10 at 13:04

  7. Вопрос про примеры 2,3. Что если функция выполняемая множеством потоков. Ловит эксепшен, или вообще нить виснет на каком-нибуть особо долгом сайте.

    SeoMazzi

    5 Фев 10 at 20:48

  8. Оберни её в try-except.

    kalombo

    9 Фев 10 at 20:27

  9. А select() или twisted юзать не пробовал?

    -

    31 Авг 11 at 06:25

Комментировать

Перед отправкой формы:
Human test by Not Captcha