Подтвердить что ты не робот

Завершить несколько потоков, когда какой-либо поток завершает задачу

Я новичок как для python, так и для потоков. Я написал код python, который работает как искатель веб-страниц и ищет сайты для определенного ключевого слова. Мой вопрос в том, как я могу использовать потоки для одновременного запуска трех разных экземпляров моего класса. Когда один из экземпляров находит ключевое слово, все три должны закрывать и останавливать сканирование в Интернете. Вот какой код.

class Crawler:
      def __init__(self):
            # the actual code for finding the keyword 

 def main():  
        Crawl = Crawler()

 if __name__ == "__main__":
        main()

Как я могу использовать потоки для того, чтобы Crawler выполнял три разных обхода одновременно?

4b9b3361

Ответ 1

Кажется, что нет (простой) способ прервать поток в Python.

Вот простой пример одновременного запуска нескольких HTTP-запросов:

import threading

def crawl():
    import urllib2
    data = urllib2.urlopen("http://www.google.com/").read()

    print "Read google.com"

threads = []

for n in range(10):
    thread = threading.Thread(target=crawl)
    thread.start()

    threads.append(thread)

# to wait until all three functions are finished

print "Waiting..."

for thread in threads:
    thread.join()

print "Complete."

С дополнительными накладными расходами вы можете использовать multi-process aproach, более мощный и позволяющий прекратить поточно-подобные процессы.

Я добавил пример, чтобы использовать это. Я надеюсь, что это будет полезно для вас:

import multiprocessing

def crawl(result_queue):
    import urllib2
    data = urllib2.urlopen("http://news.ycombinator.com/").read()

    print "Requested..."

    if "result found (for example)":
        result_queue.put("result!")

    print "Read site."

processs = []
result_queue = multiprocessing.Queue()

for n in range(4): # start 4 processes crawling for the result
    process = multiprocessing.Process(target=crawl, args=[result_queue])
    process.start()
    processs.append(process)

print "Waiting for result..."

result = result_queue.get() # waits until any of the proccess have `.put()` a result

for process in processs: # then kill them all off
    process.terminate()

print "Got result:", result

Ответ 2

Запуск потока легко:

thread = threading.Thread(function_to_call_inside_thread)
thread.start()

Создайте объект события для уведомления, когда вы закончите:

event = threading.Event()
event.wait() # call this in the main thread to wait for the event
event.set() # call this in a thread when you are ready to stop

Как только событие было запущено, вам нужно добавить методы stop() к вашим искателям.

for crawler in crawlers:
    crawler.stop()

И затем подключитесь к потокам

thread.join() # waits for the thread to finish

Если вы выполняете какое-либо количество такого рода программирования, вам нужно посмотреть на модуль eventlet. Он позволяет писать "резьбовой" код без многих недостатков потоковой передачи.

Ответ 3

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

С учетом сказанного, если ваша цель состоит в том, чтобы распараллелить (вы сказали, что "запускайте одновременно" ), вы должны знать, что в python (или, по крайней мере, в реализации по умолчанию, CPython) несколько потоков не будут действительно выполняются параллельно, даже если доступны несколько процессорных ядер. Прочтите на GIL (Global Interpreter Lock) для получения дополнительной информации.

Наконец, если вы все еще хотите продолжить, проверьте документацию Python для модуля потоковой передачи. Я бы сказал, что документы Python так же хороши, как и ссылки, с большим количеством примеров и объяснений.

Ответ 4

Для этой проблемы вы можете использовать либо модуль потоковой передачи (который, как говорили другие, не будет выполнять поточную передачу из-за GIL), либо модуль многопроцессорности (в зависимости от того, какую версию Python вы используете). У них очень похожие API, но я рекомендую многопроцессорность, поскольку это больше Pythonic, и я нахожу, что общение между процессами с Pipes довольно легко.

Вы хотите иметь свой основной цикл, который будет создавать ваши процессы, и каждый из этих процессов должен запускать ваш искатель, чтобы он возвращался к основному потоку. Ваш процесс должен прослушивать сообщение на трубке, выполнять обход и отправлять сообщение по каналу, если он что-то находит (перед завершением). Ваш основной цикл должен пересекать каждую из труб обратно, слушая это сообщение "нашел что-то". Как только он услышит это сообщение, он должен отправить его по каналам в остальные процессы, а затем дождаться их завершения.

Дополнительную информацию можно найти здесь: http://docs.python.org/library/multiprocessing.html

Ответ 5

Прежде всего, потоки не являются решением в Python. Из-за GIL Threads работает не параллельно. Таким образом, вы можете обрабатывать это с помощью многопроцессорной обработки, и вы будете ограничены количеством процессорных ядер.

Какова цель вашей работы? Вы хотите иметь сканера? Или у вас есть какие-то академические цели (изучение потоков и Python и т.д.)?

Еще один момент, Crawl тратить больше ресурсов, чем другие программы, так что продажа вашего обхода?