web-dev-qa-db-fra.com

Enfiler dans python en utilisant la file d'attente

Je voulais utiliser le filetage dans python pour télécharger beaucoup de pages Web et j'ai parcouru le code suivant qui utilise des files d'attente dans l'un des sites Web.

il met une boucle while infinie. Est-ce que chacun des threads s'exécute en continu sans fin jusqu'à ce qu'ils soient tous terminés? Suis-je en train de manquer quelque chose.

#!/usr/bin/env python
import Queue
import threading
import urllib2
import time

hosts = ["http://yahoo.com", "http://google.com", "http://Amazon.com",
"http://ibm.com", "http://Apple.com"]

queue = Queue.Queue()

class ThreadUrl(threading.Thread):
  """Threaded Url Grab"""
  def __init__(self, queue):
    threading.Thread.__init__(self)
    self.queue = queue

  def run(self):
    while True:
      #grabs Host from queue
      Host = self.queue.get()

      #grabs urls of hosts and prints first 1024 bytes of page
      url = urllib2.urlopen(Host)
      print url.read(1024)

      #signals to queue job is done
      self.queue.task_done()

start = time.time()
def main():

  #spawn a pool of threads, and pass them queue instance 
  for i in range(5):
    t = ThreadUrl(queue)
    t.setDaemon(True)
    t.start()

  #populate queue with data   
  for Host in hosts:
    queue.put(Host)

  #wait on the queue until everything has been processed     
  queue.join()

main()
print "Elapsed Time: %s" % (time.time() - start)
27
raju

Définir les threads pour être des threads daemon les fait se terminer lorsque le principal est terminé. Mais, oui, vous avez raison, vos threads s'exécuteront en continu tant qu'il y aura quelque chose dans le queue sinon il bloquera.

La documentation explique ce détail Documents de file d'attente

La documentation python Threading explique également la partie daemon.

L'ensemble du programme Python se ferme lorsqu'il ne reste plus de threads non démon vivants.

Ainsi, lorsque la file d'attente est vidée et que le queue.join reprend lorsque l'interpréteur quitte, les threads meurent.

EDIT: correction du comportement par défaut pour Queue

20
sean

Votre script fonctionne bien pour moi, donc je suppose que vous demandez ce qui se passe afin que vous puissiez mieux le comprendre. Oui, votre sous-classe place chaque thread dans une boucle infinie, en attendant que quelque chose soit mis dans la file d'attente. Quand quelque chose est trouvé, il l'attrape et fait son truc. Ensuite, la partie critique, il informe la file d'attente que c'est fait avec queue.task_done, et reprend l'attente d'un autre élément dans la file d'attente.

Pendant que tout cela se passe avec les threads de travail, le thread principal attend (se joint) jusqu'à ce que toutes les tâches de la file d'attente soient terminées, ce qui sera lorsque les threads auront envoyé le drapeau queue.task_done le même nombre de fois que les messages dans La queue . À ce stade, le thread principal se termine et se termine. Comme ce sont des threads de démons, ils se ferment également.

Ce sont des trucs sympas, des discussions et des files d'attente. C'est l'une des très bonnes parties de Python. Vous entendrez toutes sortes de choses sur la façon dont le threading dans Python est vissé avec le GIL et autres. Mais si vous savez où les utiliser (comme dans ce cas avec les E/S réseau), ils vont vraiment accélérer les choses pour vous. La règle générale est que si vous êtes lié aux E/S, essayez de tester les threads; si vous êtes lié au processeur, les threads ne sont probablement pas une bonne idée, essayez peut-être des processus à la place.

bonne chance,

Mike

8
MikeHunter