Il threading riduce significativamente il tempo di esecuzione di un programma. Scopri come implementare il threading in Python.

Il tempo di esecuzione è una delle misure comuni dell'efficienza di un programma. Più veloce è il tempo di esecuzione, migliore è il programma. Il threading è una tecnica che consente a un programma di eseguire più attività o processi contemporaneamente.

Imparerai come usare il built-in di Python filettatura modulo e il caratteristiche.concorrenti modulo. Entrambi questi moduli offrono modi semplici per creare e gestire i thread

Importanza della filettatura

Il threading riduce il tempo impiegato da un programma per completare un lavoro. Se il processo contiene più attività indipendenti, è possibile utilizzare il threading per eseguire le attività contemporaneamente, riducendo il tempo di attesa del programma per il completamento di un'attività prima di passare a quella successiva.

Ad esempio, un programma che scarica più file immagine da Internet. Questo programma può utilizzare il threading per scaricare i file in parallelo anziché uno alla volta. Ciò elimina il tempo che il programma dovrebbe attendere per il completamento del processo di download di un file prima di passare a quello successivo.

instagram viewer

Programma iniziale prima dell'infilatura

La funzione nel seguente programma rappresenta un'attività. Il compito è mettere in pausa l'esecuzione del programma per un secondo. Il programma chiama la funzione due volte creando quindi due attività. Quindi calcola il tempo impiegato per l'esecuzione dell'intero programma e lo visualizza sullo schermo.

importare tempo

start_time = tempo.perf_counter()

defpausa():
stampa('Dormire 1 secondo...')
tempo.sleep(1)
stampa("Fatto di dormire...")

pausa()
pausa()
finish_time = time.perf_counter()
stampa(f'Finito in {round (ora_fine - ora_inizio, 2)} secondo/i')

L'output mostra che il programma ha impiegato 2,01 secondi per essere eseguito. Ogni attività ha richiesto un secondo e il resto del codice ha impiegato 0,01 secondi per essere eseguito.

È possibile utilizzare il threading per eseguire contemporaneamente entrambe le attività. L'esecuzione di entrambe le attività richiederà un secondo.

Implementazione del threading utilizzando il modulo threading

Per modificare il codice iniziale per implementare il threading, importare il file filettatura modulo. Crea due thread, filo_1 E filo_2 usando il Filo classe. Chiama il inizio metodo su ogni thread per avviarne l'esecuzione. Chiama il giuntura metodo su ogni thread per attendere il completamento della loro esecuzione prima che venga eseguito il resto del programma.

importare tempo
importare filettatura
start_time = tempo.perf_counter()

defpausa():
stampa('Dormire 1 secondo...')
tempo.sleep(1)
stampa("Fatto di dormire...")

thread_1 = filettatura. Discussione (obiettivo=pausa)
thread_2 = filettatura. Discussione (obiettivo=pausa)

thread_1.start()
thread_2.start()

thread_1.join()
thread_2.join()

finish_time = time.perf_counter()
stampa(f'Finito in {round (ora_fine - ora_inizio, 2)} secondo/i')

Il programma eseguirà entrambi i thread contemporaneamente. Ciò ridurrà la quantità di tempo necessaria per eseguire entrambe le attività.

L'output mostra che il tempo impiegato per eseguire le stesse attività è di circa un secondo. Questa è la metà del tempo impiegato dal programma iniziale.

Implementazione del threading utilizzando il modulo concurrent.futures

Python 3.2 ha visto l'introduzione del futuri.concorrenti modulo. Questo modulo fornisce un'interfaccia di alto livello per l'esecuzione di attività asincrone utilizzando i thread. Fornisce un modo più semplice per eseguire attività in parallelo.

Per modificare il programma iniziale in modo che utilizzi il threading, importare il modulo concurrent.features. Usa il ThreadPoolExecutor class dal modulo concurrent.futures per creare un pool di thread. Invia il pausa funzione alla piscina due volte. IL invia metodo restituisce a futuro oggetto che rappresenta il risultato della chiamata di funzione.

Iterare sul futuri e stampare i risultati utilizzando il file risultato metodo.

importare tempo
importare futuri.concorrenti

start_time = tempo.perf_counter()

defpausa():
stampa('Dormire 1 secondo...')
tempo.sleep(1)
ritorno"Fatto di dormire..."

con futuri.concorrenti. ThreadPoolExecutor() COME esecutore:
risultati = [executor.submit (pausa) per _ In allineare(2)]
per F In concurrent.futures.as_completed (risultati):
print (f.risultato())

finish_time = time.perf_counter()

stampa(f'Finito in {round (ora_fine - ora_inizio, 2)} secondo/i')

Il modulo concurrent.features si occupa di avviare e unire i thread per te. Questo rende il tuo codice più pulito.

L'uscita è identica a quella del modulo di filettatura. Il modulo threading è utile per casi semplici in cui è necessario eseguire alcuni thread in parallelo. D'altra parte, il modulo concurrent.futures è utile per casi più complessi in cui è necessario eseguire molte attività contemporaneamente.

Utilizzo del threading in uno scenario del mondo reale

L'utilizzo dei thread per eseguire il programma precedente ha ridotto il tempo di un secondo. Nel mondo reale, i thread fanno risparmiare più tempo. Crea un programma che scarichi immagini da Internet. A partire da creazione di un nuovo ambiente virtuale. Eseguire il seguente comando nel terminale per installare il file richieste biblioteca:

richieste di installazione pip

La libreria delle richieste ti consentirà di inviare richieste HTTP. Importa la libreria delle richieste e la libreria dei tempi.

importare richieste
importare tempo

Crea un elenco di URL delle immagini che desideri scaricare. Lascia che siano almeno dieci in modo da poter notare una differenza significativa quando implementi il ​​threading.

img_urls = [
' https://images.unsplash.com/photo-1524429656589-6633a470097c',
' https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
' https://images.unsplash.com/photo-1564135624576-c5c88640f235',
' https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
' https://images.unsplash.com/photo-1522364723953-452d3431c267',
' https://images.unsplash.com/photo-1513938709626-033611b8cc03',
' https://images.unsplash.com/photo-1507143550189-fed454f93097',
' https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
' https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
' https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
' https://images.unsplash.com/photo-1516972810927-80185027ca84',
' https://images.unsplash.com/photo-1550439062-609e1531270e',
]

Passa sopra l'elenco di URL che scaricano ogni immagine nella stessa cartella che contiene il tuo progetto. Visualizza il tempo impiegato per scaricare le immagini sottraendo l'ora di fine dall'ora di inizio.

start_time = tempo.perf_counter()
per img_url In img_urls:
img_bytes = request.get (img_url).content
img_name = img_url.split('/')[3]
img_name = F'{img_name}.jpg'
con apri (nome_img, 'wb') COME img_file:
img_file.write (img_byte)
stampa(F'{img_name} è stato scaricato...')
finish_time = time.perf_counter()
stampa(f'Finito in {ora_fine - ora_inizio} secondi')

Il programma impiega circa 22 secondi per scaricare le 12 immagini. Può variare per te poiché il tempo impiegato per scaricare le immagini dipende anche dalla velocità di Internet.

Modificare il programma per utilizzare il threading utilizzando il modulo concurrent.features. Invece di un ciclo, usa una funzione. Questa è la funzione che passerai a esecutore esempio.

importare richieste
importare tempo
importare futuri.concorrenti

img_urls = [
' https://images.unsplash.com/photo-1524429656589-6633a470097c',
' https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
' https://images.unsplash.com/photo-1564135624576-c5c88640f235',
' https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
' https://images.unsplash.com/photo-1522364723953-452d3431c267',
' https://images.unsplash.com/photo-1513938709626-033611b8cc03',
' https://images.unsplash.com/photo-1507143550189-fed454f93097',
' https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
' https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
' https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
' https://images.unsplash.com/photo-1516972810927-80185027ca84',
' https://images.unsplash.com/photo-1550439062-609e1531270e',
]

start_time = tempo.perf_counter()

defscarica_immagine(img_url):
img_bytes = request.get (img_url).content
img_name = img_url.split('/')[3]
img_name = F'{img_name}.jpg'
con apri (nome_img, 'wb') COME img_file:
img_file.write (img_byte)
stampa(F'{img_name} è stato scaricato...')

con futuri.concorrenti. ThreadPoolExecutor() COME esecutore:
esecutore.map (download_image, img_urls)

finish_time = time.perf_counter()

stampa(f'Finito in {fine_ora-inizio_ora} secondi')

Dopo aver introdotto la filettatura. Il tempo si riduce notevolmente. Ci sono voluti solo 4 secondi per completare l'esecuzione del programma.

Scenari adatti alla filettatura

Alcuni degli scenari adatti per il threading sono:

  • Attività legate all'I/O: se il programma trascorre la maggior parte del tempo in attesa del completamento delle operazioni di input o output. Il threading può migliorare le prestazioni consentendo l'esecuzione di altre attività durante l'attesa del completamento delle operazioni di I/O.
  • Raschiamento web: Lo scraping Web comporta l'esecuzione di richieste HTTP e l'analisi delle risposte HTML. Il threading aiuta ad accelerare il processo consentendo di effettuare più richieste contemporaneamente.
  • Attività legate alla CPU: il threading può aiutare a migliorare le prestazioni consentendo l'esecuzione di più attività in parallelo.

Familiarizzare con il threading in altre lingue

Python non è l'unico linguaggio che supporta il threading. La maggior parte dei linguaggi di programmazione supporta una qualche forma di threading. È importante familiarizzare con l'implementazione dei thread in altre lingue. Questo ti fornisce le competenze necessarie per affrontare diversi scenari in cui può essere applicato il threading.