Domanda

Sto scrivendo un'applicazione GUI in pyglet che deve visualizzare decine a centinaia di miniature da Internet . In questo momento, sto utilizzando urllib.urlretrieve ad afferrarli, ma questo blocca ogni volta fino a quando non sono finiti, e afferra solo uno alla volta.

Io preferirei di scaricarli in parallelo e hanno ciascuno display non appena è finito, senza bloccare l'interfaccia grafica in qualsiasi momento. Qual è il modo migliore per fare questo?

Non so molto circa le discussioni, ma sembra che il filettatura modulo potrebbe aiutare? O forse c'è un modo semplice che ho trascurato.

È stato utile?

Soluzione

Probabilmente beneficiare di threading o multiprocessing moduli . In realtà non è necessario creare tutte quelle classi Thread a base da soli, c'è un metodo più semplice utilizzando 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)

Altri suggerimenti

Come si sospetta, questa è una situazione ideale per la filettatura. Qui è una breve guida che ho trovato immensamente utile quando si fa il mio primo pezzo di filettatura in Python.

Come lei ha giustamente indicato, è possibile creare un numero di thread, ognuno dei quali è responsabile per l'esecuzione di operazioni urlretrieve. Questo permette al filo principale applicazione continua.

Ecco un tutorial sulla filettatura in pitone: http://heather.cs.ucdavis.edu/~matloff/Python/ PyThreads.pdf

Ecco un esempio di come utilizzare threading.Thread. Basta sostituire il nome della classe con il proprio e la funzione di corsa con il proprio. Si noti che threading è grande per IO limitato le applicazioni come il vostro di e può davvero accelerarlo. Utilizzando pythong filettatura esclusivamente per il calcolo in pitone norma non aiuta perché solo un thread può calcolare alla volta.

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

Sono disponibili le seguenti opzioni:

  • Discussioni: più semplice, ma non scala bene
  • twisted:. Media difficoltà, scala bene ma condivide CPU a causa di GIL e di essere a thread singolo
  • Multiprocessing: più difficile. Scala bene se si sa come scrivere il proprio ciclo di eventi.

Mi raccomando solo usando le discussioni a meno che non avete bisogno di un Fetcher scala industriale.

Si sia bisogno di usare i thread, o una libreria di rete asincrono come ritorto . Ho il sospetto che l'uso di fili potrebbe essere più semplice nel vostro particolare caso d'uso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top