web-dev-qa-db-fra.com

Mettre fin à plusieurs threads lorsqu'un des threads termine une tâche

Je suis nouveau au python et aux threads. J'ai écrit du code python qui agit comme un robot d'indexation Web et recherche un mot-clé spécifique sur les sites. Ma question est la suivante: comment utiliser des threads pour exécuter trois instances différentes de ma classe en même temps. Lorsque l'une des instances trouve le mot clé, toutes les trois doivent être fermées et cesser d'analyser le Web. Voici du code.

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

 def main():  
        Crawl = Crawler()

 if __== "__main__":
        main()

Comment utiliser des threads pour que Crawler effectue trois analyses différentes en même temps?

33
user446836

Il ne semble pas y avoir de moyen (simple) de terminer un thread en Python.

Voici un exemple simple d'exécution de plusieurs requêtes HTTP en parallèle:

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."

Avec une surcharge supplémentaire, vous pouvez utiliser un multi-process aproach qui est plus puissant et vous permet de terminer les processus de type thread. 

J'ai étendu l'exemple pour l'utiliser. J'espère que cela vous sera utile:

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
54
Jeremy Banks

Démarrer un fil est facile:

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

Créez un objet événement à notifier lorsque vous avez terminé:

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

Une fois que l'événement est déclenché, vous devez ajouter des méthodes stop () à vos robots d'exploration.

for crawler in crawlers:
    crawler.stop()

Et puis appelez rejoindre sur les discussions

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

Si vous faites ce type de programmation, vous voudrez peut-être consulter le module Eventlet. Il vous permet d'écrire du code "threaded" sans avoir beaucoup des inconvénients du threading.

6
Winston Ewert

Tout d'abord, si vous débutez dans le langage python, je ne recommanderais pas encore de faire face aux threads. Habituez-vous à la langue, puis abordez le multi-threading.

Cela dit, si votre objectif est de paralléliser (vous avez dit "exécuter en même temps"), vous devez savoir qu'en python (ou au moins dans l'implémentation par défaut, CPython) plusieurs threads NE s'exécutent PAS réellement en parallèle même si plusieurs cœurs de processeur sont disponibles. Consultez le GIL (Global Interpreter Lock) pour plus d’informations.

Enfin, si vous voulez continuer, consultez la documentation Python pour le module de threading. Je dirais que la documentation de Python est aussi bonne que les références, avec de nombreux exemples et explications.

5
slezica

Pour ce problème, vous pouvez utiliser le module de threading (qui, comme d'autres l'ont dit, ne réalisera pas de véritable thread en raison de la GIL) ou le module de multitraitement (selon la version de Python que vous utilisez). Ils ont des API très similaires, mais je recommande le multitraitement, car il s'agit davantage de Pythonic, et je trouve que la communication entre processus avec Pipes est assez facile.

Vous voudrez avoir votre boucle principale, qui créera vos processus, et chacun de ces processus doit exécuter votre robot d'exploration avec un tuyau de retour au thread principal. Votre processus doit écouter un message sur le tuyau, faire une analyse et renvoyer un message sur le tuyau s'il trouve quelque chose (avant de terminer). Votre boucle principale doit boucler sur chacun des canaux, en écoutant ce message "trouvé quelque chose". Une fois qu'il a entendu ce message, il doit le renvoyer par la suite aux processus restants, puis attendre la fin de ceux-ci.

Plus d'informations peuvent être trouvées ici: http://docs.python.org/library/multiprocessing.html

0
Robotica

Tout d'abord, le threading n'est pas une solution en Python. En raison de GIL, Threads ne fonctionne pas en parallèle. Ainsi, vous pouvez gérer cela avec le multitraitement et vous serez limité par le nombre de cœurs de processeur.

Quel est l'objectif de votre travail? Vous voulez avoir un robot? Ou vous avez des objectifs académiques (apprentissage du threading et de Python, etc.)?

Un autre point, Crawl gaspille plus de ressources que d’autres programmes, alors quelle est la vente de votre analyse?

0