Threading výrazne znižuje čas vykonávania programu. Zistite, ako implementovať vlákna v Pythone.

Čas realizácie je jedným z bežných meradiel účinnosti programu. Čím rýchlejší je čas vykonania, tým lepší je program. Threading je technika, ktorá umožňuje programu vykonávať viacero úloh alebo procesov súčasne.

Naučíte sa používať vstavaný Python závitovanie modul a súbežné.vlastnosti modul. Oba tieto moduly ponúkajú jednoduché spôsoby vytvárania a správy vlákien

Význam závitovania

Threading znižuje množstvo času, ktorý program potrebuje na dokončenie úlohy. Ak úloha obsahuje viacero nezávislých úloh, môžete použiť vlákno na spustenie úloh súčasne, čím sa skráti čas čakania programu na dokončenie jednej úlohy pred prechodom na ďalšiu.

Napríklad program, ktorý sťahuje viacero obrázkových súborov z internetu. Tento program môže využívať vlákna na sťahovanie súborov paralelne a nie po jednom. Tým sa eliminuje čas, ktorý by program musel čakať na dokončenie procesu sťahovania jedného súboru, než prejde na ďalší.

Úvodný program pred závitovaním

Funkcia v nasledujúcom programe predstavuje úlohu. Úlohou je pozastaviť vykonávanie programu na jednu sekundu. Program volá funkciu dvakrát, čím vytvára dve úlohy. Potom vypočíta čas potrebný na spustenie celého programu a potom ho zobrazí na obrazovke.

importovať čas

start_time = time.perf_counter()

defpauza():
vytlačiť ('Spím 1 sekundu...')
čas.spánok(1)
vytlačiť ('Hotovo spať...')

pauza()
pauza()
finish_time = time.perf_counter()
vytlačiť (f'Dokončené v {round (finish_time - start_time, 2)} sekunda (s)')

Výstup ukazuje, že spustenie programu trvalo 2,01 sekundy. Každá úloha trvala jednu sekundu a spustenie zvyšku kódu trvalo 0,01 sekundy.

Môžete použiť vlákno na súčasné vykonávanie oboch úloh. Vykonanie oboch úloh bude trvať jednu sekundu.

Implementácia závitovania pomocou modulu závitovania

Ak chcete upraviť počiatočný kód na implementáciu vlákien, importujte súbor závitovanie modul. Vytvorte dve vlákna, vlákno_1 a vlákno_2 pomocou Niť trieda. Zavolajte na začať metóda na každom vlákne na spustenie jeho vykonávania. Zavolajte na pripojiť sa metódu na každom vlákne, aby počkal na dokončenie ich vykonania skôr, ako sa spustí zvyšok programu.

importovať čas
importovať závitovanie
start_time = time.perf_counter()

defpauza():
vytlačiť ('Spím 1 sekundu...')
čas.spánok(1)
vytlačiť ('Hotovo spať...')

thread_1 = závitovanie. Vlákno (cieľ=pauza)
thread_2 = závitovanie. Vlákno (cieľ=pauza)

thread_1.start()
thread_2.start()

thread_1.join()
thread_2.join()

finish_time = time.perf_counter()
vytlačiť (f'Dokončené v {round (finish_time - start_time, 2)} sekunda (s)')

Program spustí obe vlákna súčasne. Tým sa zníži množstvo času potrebného na splnenie oboch úloh.

Výstup ukazuje, že čas potrebný na spustenie rovnakých úloh je približne sekunda. To je polovica času, ktorý trval pôvodný program.

Implementácia vlákna pomocou modulu concurrent.futures

Python 3.2 videl predstavenie súbežné.budúcnosti modul. Tento modul poskytuje rozhranie na vysokej úrovni na vykonávanie asynchrónnych úloh pomocou vlákien. Poskytuje jednoduchší spôsob paralelného vykonávania úloh.

Ak chcete upraviť počiatočný program na používanie vlákien, importujte modul concurrent.features. Použi ThreadPoolExecutor triedy z modulu concurrent.futures na vytvorenie skupiny vlákien. Odoslať pauza ísť do bazéna dvakrát. The Predložiť metóda vracia a budúcnosti objekt, ktorý predstavuje výsledok volania funkcie.

Iterovať cez futures a vytlačte ich výsledky pomocou výsledok metóda.

importovať čas
importovať súbežné.budúcnosti

start_time = time.perf_counter()

defpauza():
vytlačiť ('Spím 1 sekundu...')
čas.spánok(1)
vrátiť'Hotovo spať...'

s súbežné.budúcnosti. ThreadPoolExecutor() ako vykonávateľ:
výsledky = [executor.submit (pauza) pre _ v rozsah(2)]
pre f v concurrent.futures.as_completed (výsledky):
vytlačiť (f.vysledok())

finish_time = time.perf_counter()

vytlačiť (f'Dokončené v {round (finish_time - start_time, 2)} sekunda (s)')

Modul concurrent.features sa postará o spustenie a spájanie vlákien za vás. Vďaka tomu bude váš kód čistejší.

Výstup je rovnaký ako výstup závitového modulu. Modul vlákna je užitočný v jednoduchých prípadoch, keď potrebujete spustiť niekoľko vlákien paralelne. Na druhej strane je modul concurrent.futures užitočný pre zložitejšie prípady, keď potrebujete spúšťať veľa úloh súčasne.

Použitie vlákien v scenári skutočného sveta

Použitie vlákien na spustenie vyššie uvedeného programu skrátilo čas o jednu sekundu. V reálnom svete vlákna šetria viac času. Vytvorte program, ktorý stiahne obrázky z internetu. Začnite tým vytvorenie nového virtuálneho prostredia. Spustite nasledujúci príkaz v termináli a nainštalujte ho žiadosti knižnica:

požiadavky na inštaláciu pip

Knižnica požiadaviek vám umožní odosielať požiadavky HTTP. Importujte knižnicu požiadaviek a časovú knižnicu.

importovať žiadosti
importovať čas

Vytvorte zoznam adries URL obrázkov, ktoré chcete stiahnuť. Nech je ich aspoň desať, aby ste si pri implementácii závitovania všimli výrazný rozdiel.

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',
]

Prejdite cez zoznam URL, ktoré sťahujú každý obrázok do rovnakého priečinka, ktorý obsahuje váš projekt. Zobrazte čas potrebný na stiahnutie obrázkov odčítaním času ukončenia od času začiatku.

start_time = time.perf_counter()
pre img_url v img_urls:
img_bytes = requesty.get (img_url).obsah
img_name = img_url.split('/')[3]
názov_img = f'{img_name}.jpg'
s open (img_name, 'wb') ako img_file:
img_file.write (img_bytes)
vytlačiť (f'{img_name} bol stiahnutý...“)
finish_time = time.perf_counter()
vytlačiť (f'Dokončené v {finish_time - start_time} sekundy)

Stiahnutie 12 obrázkov trvá programu približne 22 sekúnd. Môže sa líšiť, pretože čas potrebný na stiahnutie obrázkov závisí aj od rýchlosti vášho internetu.

Upravte program tak, aby používal vlákna pomocou modulu concurrent.features. Namiesto slučky použite funkciu. Toto je funkcia, ktorú odovzdáte exekútor príklad.

importovať žiadosti
importovať čas
importovať súbežné.budúcnosti

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 = time.perf_counter()

defdownload_image(img_url):
img_bytes = requesty.get (img_url).obsah
img_name = img_url.split('/')[3]
názov_img = f'{img_name}.jpg'
s open (img_name, 'wb') ako img_file:
img_file.write (img_bytes)
vytlačiť (f'{img_name} bol stiahnutý...“)

s súbežné.budúcnosti. ThreadPoolExecutor() ako vykonávateľ:
executor.map (download_image, img_urls)

finish_time = time.perf_counter()

vytlačiť (f'Dokončené v {finish_time-start_time} sekundy)

Po zavedení navliekania. Čas sa výrazne znižuje. Dokončenie vykonania programu trvalo iba 4 sekundy.

Scenáre vhodné pre závitovanie

Niektoré zo scenárov vhodných na vytváranie vlákien sú:

  • I/O viazané úlohy: Ak program strávi väčšinu času čakaním na dokončenie vstupných alebo výstupných operácií. Threading môže zlepšiť výkon tým, že umožní vykonanie iných úloh počas čakania na dokončenie I/O operácií.
  • Zoškrabovanie webu: Web scraping zahŕňa vytváranie požiadaviek HTTP a analýzu odpovedí HTML. Threading pomáha urýchliť proces tým, že vám umožňuje vykonávať viacero požiadaviek súčasne.
  • Úlohy viazané na CPU: Threading môže pomôcť zlepšiť výkon tým, že umožní paralelné vykonávanie viacerých úloh.

Oboznámte sa s vláknom v iných jazykoch

Python nie je jediný jazyk, ktorý podporuje vytváranie vlákien. Väčšina programovacích jazykov podporuje nejakú formu vlákna. Je dôležité, aby ste sa oboznámili s implementáciou vlákien v iných jazykoch. To vás vybaví potrebnými zručnosťami na riešenie rôznych scenárov, v ktorých sa môže použiť vytváranie vlákien.