Threadingul reduce semnificativ timpul de execuție al unui program. Aflați cum să implementați threading în Python.
Timpul de execuție este una dintre măsurile comune ale eficienței unui program. Cu cât timpul de execuție este mai rapid, cu atât programul este mai bun. Threadingul este o tehnică care permite unui program să execute mai multe sarcini sau procese simultan.
Veți învăța cum să utilizați Python încorporat filetat modulul și concurente.caracteristici modul. Ambele module oferă modalități simple de a crea și gestiona fire
Importanța filetării
Threadingul reduce timpul necesar unui program pentru a finaliza o lucrare. Dacă jobul conține mai multe sarcini independente, puteți utiliza threading pentru a rula sarcinile concomitent, reducând timpul de așteptare al programului pentru finalizarea unei sarcini înainte de a trece la următoarea.
De exemplu, un program care descarcă mai multe fișiere imagine de pe internet. Acest program poate utiliza threading pentru a descărca fișierele în paralel și nu pe rând. Acest lucru elimină timpul pe care programul ar trebui să aștepte pentru finalizarea procesului de descărcare a unui fișier înainte de a trece la următorul.
Programul inițial înainte de threading
Funcția din programul următor reprezintă o sarcină. Sarcina este de a întrerupe execuția programului pentru o secundă. Programul apelează funcția de două ori, creând astfel două sarcini. Apoi calculează timpul necesar pentru rularea întregului program și apoi îl afișează pe ecran.
import timp
start_time = time.perf_counter()
defpauză():
imprimare(„Doarme 1 secundă...”)
timp.somn(1)
imprimare(„Terminat de dormit...”)
pauză()
pauză()
finish_time = time.perf_counter()
imprimare(f'Terminat în {round (finish_time - start_time, 2)} secunda (e)')
Ieșirea arată că programul a durat 2,01 secunde pentru a se executa. Fiecare sarcină a durat o secundă, iar restul codului a durat 0,01 secunde pentru a se executa.
Puteți folosi threading pentru a executa simultan ambele sarcini. Ambele sarcini vor dura o secundă pentru a fi executate.
Implementarea Threading Utilizând modulul Threading
Pentru a modifica codul inițial pentru a implementa threading, importați filetat modul. Creați două fire, fir_1 și firul_2 folosind Fir clasă. Suna start metoda pe fiecare fir pentru a începe execuția acestuia. Suna a te alatura metoda pe fiecare fir pentru a aștepta finalizarea execuției lor înainte ca restul programului să se execute.
import timp
import filetat
start_time = time.perf_counter()defpauză():
imprimare(„Doarme 1 secundă...”)
timp.somn(1)
imprimare(„Terminat de dormit...”)thread_1 = threading. Subiect (țintă=pauză)
thread_2 = threading. Subiect (țintă=pauză)thread_1.start()
thread_2.start()thread_1.join()
thread_2.join()
finish_time = time.perf_counter()
imprimare(f'Terminat în {round (finish_time - start_time, 2)} secunda (e)')
Programul va rula ambele fire simultan. Acest lucru va reduce timpul necesar pentru îndeplinirea ambelor sarcini.
Rezultatul arată că timpul necesar pentru a rula aceleași sarcini este de aproximativ o secundă. Acesta este jumătate din timpul programului inițial.
Implementarea Threading folosind modulul concurrent.futures
Python 3.2 a văzut introducerea concurente.viitoare modul. Acest modul oferă o interfață de nivel înalt pentru executarea sarcinilor asincrone folosind fire. Oferă o modalitate mai simplă de a executa sarcini în paralel.
Pentru a modifica programul inițial pentru a utiliza threading, importați modulul concurrent.features. Folosește ThreadPoolExecutor clasă din modulul concurrent.futures pentru a crea un grup de fire. Trimiteți pauză funcţionează la piscină de două ori. The Trimite metoda returnează a viitor obiect care reprezintă rezultatul apelului de funcție.
Iterați peste viitoare și imprimați rezultatele utilizând rezultat metodă.
import timp
import concurente.viitoarestart_time = time.perf_counter()
defpauză():
imprimare(„Doarme 1 secundă...”)
timp.somn(1)
întoarcere„Terminat de dormit...”cu concurente.viitoare. ThreadPoolExecutor() la fel de executor testamentar:
rezultate = [executor.submit (pause) pentru _ în gamă(2)]
pentru f în concurrent.futures.as_completed (rezultate):
imprimare (f.result())finish_time = time.perf_counter()
imprimare(f'Terminat în {round (finish_time - start_time, 2)} secunda (e)')
Modulul concurrent.features se ocupă de pornirea și unirea firelor pentru tine. Acest lucru vă face codul mai curat.
Ieșirea este identică cu cea a modulului de filetare. Modulul de threading este util pentru cazurile simple în care trebuie să rulați câteva fire în paralel. Pe de altă parte, modulul concurrent.futures este util pentru cazuri mai complexe în care trebuie să rulați mai multe sarcini simultan.
Utilizarea Threading într-un scenariu din lumea reală
Utilizarea thread-urilor pentru a rula programul de mai sus a redus timpul cu o secundă. În lumea reală, firele economisesc mai mult timp. Creați un program care descarcă imagini de pe internet. Începe prin crearea unui nou mediu virtual. Rulați următoarea comandă în terminal pentru a instala cereri bibliotecă:
solicitări de instalare pip
Biblioteca de solicitări vă va permite să trimiteți solicitări HTTP. Importați biblioteca de solicitări și biblioteca de timp.
import cereri
import timp
Creați o listă de adrese URL ale imaginilor pe care doriți să le descărcați. Lăsați-le să fie de cel puțin zece, astfel încât să puteți observa o diferență semnificativă atunci când implementați 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',
]
Încercați lista de adrese URL care descarcă fiecare imagine în același folder care conține proiectul dvs. Afișați timpul necesar pentru descărcarea imaginilor scăzând timpul de încheiere de la ora de începere.
start_time = time.perf_counter()
pentru img_url în img_urls:
img_bytes = requests.get (img_url).content
img_name = img_url.split('/')[3]
img_name = f'{img_name}.jpg'
cu deschide (nume_img, 'wb') la fel de fisier_img:
img_file.write (img_bytes)
imprimare(f'{img_name} a fost descărcat...')
finish_time = time.perf_counter()
imprimare(f'Terminat în {finish_time - start_time} secunde')
Programul durează aproximativ 22 de secunde pentru a descărca cele 12 imagini. Poate varia pentru dvs., deoarece timpul necesar pentru descărcarea imaginilor depinde și de viteza internetului dvs.
Modificați programul pentru a utiliza threading folosind modulul concurrent.features. În loc de o buclă, utilizați o funcție. Aceasta este funcția pe care o veți transmite executor testamentar instanță.
import cereri
import timp
import concurente.viitoareimg_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 = time.perf_counter()
defdownload_image(img_url):
img_bytes = requests.get (img_url).content
img_name = img_url.split('/')[3]
img_name = f'{img_name}.jpg'
cu deschide (nume_img, 'wb') la fel de fisier_img:
img_file.write (img_bytes)
imprimare(f'{img_name} a fost descărcat...')cu concurente.viitoare. ThreadPoolExecutor() la fel de executor testamentar:
executor.map (descărcare_imagine, img_urls)finish_time = time.perf_counter()
imprimare(f'Terminat în {finish_time-start_time} secunde')
După introducerea filetului. Timpul se reduce semnificativ. A durat doar 4 secunde pentru a finaliza execuția programului.
Scenarii potrivite pentru threading
Unele dintre scenariile potrivite pentru threading sunt:
- Sarcini legate de I/O: Dacă programul petrece cea mai mare parte a timpului așteptând finalizarea operațiunilor de intrare sau de ieșire. Threadingul poate îmbunătăți performanța, permițând executarea altor sarcini în timp ce se așteaptă finalizarea operațiunilor I/O.
- Scraping web: Web scraping implică efectuarea de solicitări HTTP și analizarea răspunsurilor HTML. Threading ajută la accelerarea procesului, permițându-vă să faceți mai multe solicitări simultan.
- Sarcini legate de CPU: Threadingul poate ajuta la îmbunătățirea performanței, permițând executarea în paralel a mai multor sarcini.
Familiarizați-vă cu Threading în alte limbi
Python nu este singurul limbaj care acceptă threading. Majoritatea limbajelor de programare acceptă o anumită formă de threading. Este important să vă familiarizați cu implementarea thread-urilor în alte limbi. Acest lucru vă oferă abilitățile necesare pentru a aborda diferite scenarii în care se poate aplica threading.