2009-06-11 6 views
2

J'écris une application GUI dans Pyglet qui doit afficher des dizaines à des centaines de vignettes de l'Internet. En ce moment, j'utilise urllib.urlretrieve pour les attraper, mais cela bloque à chaque fois jusqu'à ce qu'ils soient finis, et ne saisissent qu'un seul à la fois.Comment faire une extraction d'URL non bloquante en Python

Je préférerais les télécharger en parallèle et les afficher dès que c'est fini, sans bloquer l'interface graphique à aucun moment. Quelle est la meilleure façon de procéder?

Je ne sais pas grand-chose sur les threads, mais il semble que le module threading pourrait aider? Ou peut-être y a-t-il un moyen facile que j'ai oublié.

Répondre

3

Vous aurez probablement bénéficier de threading ou multiprocessing modules. Vous n'avez pas réellement besoin de créer toutes ces Thread cours par vous-même à base, il existe une méthode plus simple en utilisant Pool.map:

from multiprocessing import Pool 

def fetch_url(url): 
    # Fetch the URL contents and save it anywhere you need and 
    # return something meaningful (like filename or error code), 
    # if you wish. 
    ... 

pool = Pool(processes=4) 
result = pool.map(f, image_url_list) 
+0

Existe-t-il un équivalent de Pool pour les threads? Cela ressemble à des processus distincts, qui peuvent être plus lourds que nécessaire. – Kiv

+0

Semble qu'il n'y a pas intégré, mais j'ai trouvé ceci: http://www.chrisarndt.de/projects/threadpool/ et il semble assez similaire. – drdaeman

+0

Merci, threadpool fonctionne très bien. – Kiv

2

Comme vous le suspectiez, c'est une situation idéale pour l'enfilage. Here est un petit guide que j'ai trouvé extrêmement utile lorsque j'ai fait mon propre premier morceau de threading en python.

2

Comme vous l'avez indiqué à juste titre, vous pouvez créer un certain nombre de threads, dont chacun est responsable de l'exécution des opérations urlretrieve. Cela permet au thread principal de continuer sans interruption.

Voici un tutoriel sur le filetage en python: http://heather.cs.ucdavis.edu/~matloff/Python/PyThreads.pdf

+0

Merci pour le tutoriel, c'était utile. – Kiv

2

Voici un exemple de la façon d'utiliser threading.Thread. Remplacez simplement le nom de la classe par le vôtre et la fonction d'exécution par la vôtre. Notez que le thread est idéal pour les applications restreintes IO comme la vôtre et peut vraiment l'accélérer. L'utilisation de threads pythong strictement pour le calcul en python standard n'aide pas car un seul thread peut calculer à la fois.

import threading, time 
class Ping(threading.Thread): 
    def __init__(self, multiple): 
     threading.Thread.__init__(self) 
     self.multiple = multiple 
    def run(self): 
     #sleeps 3 seconds then prints 'pong' x times 
     time.sleep(3) 
     printString = 'pong' * self.multiple 

pingInstance = Ping(3) 
pingInstance.start() #your run function will be called with the start function 
print "pingInstance is alive? : %d" % pingInstance.isAlive() #will return True, or 1 
print "Number of threads alive: %d" % threading.activeCount() 
#main thread + class instance 
time.sleep(3.5) 
print "Number of threads alive: %d" % threading.activeCount() 
print "pingInstance is alive?: %d" % pingInstance.isAlive() 
#isAlive returns false when your thread reaches the end of it's run function. 
#only main thread now 
0

Vous avez besoin soit d'utiliser des fils, ou une bibliothèque de réseau asynchrone tels que Twisted. Je soupçonne que l'utilisation de threads pourrait être plus simple dans votre cas d'utilisation particulier.

1

Vous avez ces choix:

  • Threads: plus facile, mais est redimensionnée pas bien
  • Twisted: difficulté moyenne, des échelles bien, mais des parts d'UC en raison de GIL et étant un seul thread.
  • Multi-traitement: le plus dur. Échelle bien si vous savez écrire votre propre boucle d'événement.

Je recommande d'utiliser des threads sauf si vous avez besoin d'un extracteur à échelle industrielle.

Questions connexes