Programiranje

Začnite z async v Pythonu

Asinhrono programiranje, oz asinh na kratko je značilnost mnogih sodobnih jezikov, ki programu omogoča, da žonglira z več operacijami, ne da bi čakal ali prekinil katero koli od njih. To je pameten način za učinkovito obvladovanje nalog, kot so omrežni ali datotečni V / I, kjer večino časa programa porabimo v čakanju, da se opravilo konča.

Razmislite o programu za strganje po spletu, ki odpre 100 omrežnih povezav. Lahko odprete eno povezavo, počakate na rezultate, nato odprete naslednjo in počakate na rezultate itd. Večino časa se program izvaja v čakanju na omrežni odziv, ne da bi opravil dejansko delo.

Async vam nudi učinkovitejši način: Odprite vseh 100 povezav hkrati in nato preklopite med vsako aktivno povezavo, ko vrnejo rezultate. Če ena povezava ne vrne rezultatov, preklopite na naslednjo itd., Dokler vse povezave ne vrnejo svojih podatkov.

Sintaksa asinhronizacije je zdaj standardna značilnost v Pythonu, toda dolgoletni Pythonisti, ki so vajeni delati po eno stvar, imajo lahko težave z ovijanjem glave. V tem članku bomo raziskali, kako deluje asinhrono programiranje v Pythonu in kako ga uporabiti.

Upoštevajte, da če želite v Pythonu uporabljati asinhronizacijo, je najbolje uporabiti Python 3.7 ali Python 3.8 (najnovejšo različico tega pisanja). Uporabili bomo Pythonovo asinhransko sintakso in pomožne funkcije, kot so opredeljene v teh različicah jezika.

Kdaj uporabiti asinhrono programiranje

Na splošno so najboljši časi za uporabo asinhronizacije takrat, ko poskušate opraviti delo, ki ima naslednje lastnosti:

  • Delo traja dolgo.
  • Zamuda vključuje čakanje na I / O (diskovne ali omrežne) operacije, ne pa na izračun.
  • Delo vključuje veliko I / O operacij, ki se dogajajo naenkrat, ali ena ali več V / I operacij, ki se zgodi, ko poskušate opraviti tudi druge naloge.

Async vam omogoča, da vzporedno nastavite več nalog in jih učinkovito pregledujete, ne da bi blokirali preostalo aplikacijo.

Nekaj ​​primerov nalog, ki dobro delujejo z asinhronizacijo:

  • Strganje po spletu, kot je opisano zgoraj.
  • Omrežne storitve (npr. Spletni strežnik ali ogrodje).
  • Programi, ki usklajujejo rezultate iz več virov, ki dolgo časa vrnejo vrednosti (na primer hkratne poizvedbe v zbirki podatkov).

Pomembno je omeniti, da se asinhrono programiranje razlikuje od večnitnega ali večprocesorskega. Vse asinhrične operacije se izvajajo v isti niti, vendar se med seboj po potrebi podajo, zaradi česar je asinhronizacija za številne vrste nalog učinkovitejša od navojev ali večprocesorske obdelave. (Več o tem spodaj.)

Python asinhčakati in asincio

Python je pred kratkim dodal dve ključni besedi, asinh in čakati, za ustvarjanje async operacij. Razmislite o tem skriptu:

def get_server_status (server_addr) # Morebitno dolgotrajna operacija ... vrni server_status def server_ops () results = [] results.append (get_server_status ('addr1.server') results.append (get_server_status ('addr2.server') return) rezultatov 

Asinhna različica istega skripta - nedelujoča, ravno toliko, da nam predstavi, kako deluje sintaksa - je lahko videti tako.

async def get_server_status (server_addr) # Potencialno dolgotrajna operacija ... vrni server_status async def server_ops () results = [] results.append (await get_server_status ('addr1.server') results.append (await get_server_status ('addr2. strežnik ') vrne rezultate 

Funkcije s predpono asinh ključne besede postanejo asinhrone funkcije, znane tudi kot podprogrami. Programi se obnašajo drugače kot običajne funkcije:

  • Programi lahko uporabljajo drugo ključno besedo, čakati, ki koroutini omogoča, da brez blokiranja počaka na rezultate druge koroutine. Dokler se rezultati ne vrnejo iz čakatied edini program Python prosto preklaplja med drugimi tekočimi programi.
  • Programi lahko samo klicati od drugih asinh funkcije. Če tečeš server_ops () ali get_server_status () kakršno je iz telesa scenarija, ne boste dobili njihovih rezultatov; dobili boste Python program, ki ga ni mogoče neposredno uporabiti.

Torej, če ne moremo poklicati asinh funkcije iz neasinhronih funkcij in ne moremo zagnati asinh funkcije, kako jih uporabljamo? Odgovor: Z uporabo asincio knjižnica, ki premošča asinh in preostali del Pythona.

Python asinhčakati in asincio primer

Tu je primer (spet ne funkcionalen, ampak ponazorljiv), kako lahko z uporabo napišemo aplikacijo za strganje po spletu asinh in asincio. Ta skript zajema seznam URL-jev in uporablja več primerov datoteke asinh funkcija iz zunanje knjižnice (read_from_site_async ()), da jih prenesete in združite rezultate.

import asyncio from web_scraping_library import read_from_site_async async def main (url_list): return await asyncio.gather (* [read_from_site_async (_) for _ in url_list]) urls = ['//site1.com','//othersite.com', '//newsite.com'] rezultati = asyncio.run (glavni (urls)) print (rezultati) 

V zgornjem primeru uporabljamo dve pogosti asincio funkcije:

  • asyncio.run () se uporablja za zagon asinh delujejo iz neasinhronega dela naše kode in tako sprožijo vse asinhronske dejavnosti programa. (Tako tečemo glavni ().)
  • asyncio.gather () ima eno ali več asinhrono okrašenih funkcij (v tem primeru več primerov read_from_site_async () iz naše hipotetične knjižnice za strganje po spletu), jih zažene in čaka, da se pojavijo vsi rezultati.

Ideja je v tem, da začnemo operacijo branja hkrati za vsa spletna mesta zbrati rezultati, ko prispejo (torej asyncio.gather ()). Ne čakamo, da se katera koli operacija zaključi, preden se premaknemo na naslednjo.

Komponente Python async aplikacij

Omenili smo že, kako aplikacije Python async uporabljajo koroutine kot svojo glavno sestavino, pri čemer se opirajo na asincio knjižnica, da jih zažene. Nekaj ​​drugih elementov je prav tako ključnih za asinhrone aplikacije v Pythonu:

Zanke dogodkov

The asincio knjižnica ustvarja in upravlja zanke dogodkov, mehanizmi, ki izvajajo koprovine, dokler se ne dokončajo. V procesu Pythona se mora naenkrat izvajati samo ena zanka dogodkov, če le zato, da programer lažje spremlja, kaj gre vanj.

Naloge

Ko oddate koprogram zanki dogodka v obdelavo, lahko dobite nazaj a Naloga objekt, ki ponuja način za nadzor vedenja koproteta zunaj zanke dogodka. Če morate na primer preklicati zagnano nalogo, lahko to storite tako, da pokličete nalogo .cancel () metoda.

Tu je nekoliko drugačna različica skripta za strganje strani, ki prikazuje zanko dogodka in opravila na delu:

import asyncio from web_scraping_library import read_from_site_async tasks = [] async def main (url_list): za n v url_list: tasks.append (asyncio.create_task (read_from_site_async (n))) print (tasks) return await asyncio.gather = ['//site1.com','//othersite.com','//newsite.com'] zanka = asyncio.get_event_loop () rezultati = loop.run_until_complete (glavni (urls)) print (rezultati) 

Ta skript bolj eksplicitno uporablja zanko dogodkov in predmete opravil.

  • The .get_event_loop () metoda nam zagotavlja objekt, ki nam omogoča neposreden nadzor nad zanko dogodka, tako da ji programsko posreduje asinhrične funkcije prek .run_until_complete (). V prejšnjem skriptu smo lahko uporabili samo eno funkcijo asinhracije na najvišji ravni asyncio.run (). Mimogrede, .run_until_complete () naredi natanko to, kar piše: zažene vse dobavljene naloge, dokler niso končane, nato pa rezultate vrne v enem paketu.
  • The .create_task () metoda vzame funkcijo za zagon, vključno s svojimi parametri, in nam vrne a Naloga predmet, da ga zaženete. Tu predložimo vsak URL kot ločen Naloga v zanko dogodka in shranite datoteko Naloga predmetov na seznamu. Upoštevajte, da lahko to storimo samo znotraj zanke dogodkov - torej znotraj asinh funkcijo.

Koliko nadzora potrebujete nad zanko dogodka in njegovimi nalogami, bo odvisno od tega, kako kompleksna je aplikacija, ki jo gradite. Če želite oddati nabor fiksnih opravil za sočasno izvajanje, tako kot pri našem spletnem strgalniku, ne boste potrebovali veliko nadzora - ravno toliko, da boste lahko zagnali opravila in zbrali rezultate.

Če pa ustvarjate popolno spletno ogrodje, boste želeli veliko več nadzora nad vedenjem podprogramov in zanke dogodkov. Na primer, morda boste morali v primeru zrušitve aplikacije elegantno zapreti zanko dogodka ali zagnati naloge na varen način, če zanko dogodka prikličete iz druge niti.

Async vs navojem vs multiprocessing

Na tej točki se morda sprašujete, zakaj uporabljati asinhronizacijo namesto niti ali večprocesorske obdelave, ki sta že dolgo na voljo v Pythonu?

Prvič, ključna razlika je med asinhronizacijo in nitmi ali večprocesorsko obdelavo, tudi razen tega, kako se te stvari izvajajo v Pythonu. Async je približno sočasnost, medtem ko gre za niti in večprocesorsko obdelavo vzporednost. Sočasnost vključuje učinkovito delitev časa med več opravili naenkrat - npr. Preverjanje e-pošte med čakanjem na register v trgovini. Vzporednost vključuje več agentov, ki obdelujejo več nalog vzporedno - npr. V trgovini z živili je odprtih pet ločenih registrov.

Async je večino časa dober nadomestek za navoja, saj je navoj izveden v Pythonu. To pa zato, ker Python ne uporablja niti OS, temveč lastne kooperativne niti, kjer se v tolmaču naenkrat izvaja le ena nit. V primerjavi s kooperativnimi nitmi async ponuja nekaj ključnih prednosti:

  • Async funkcije so veliko lažje kot niti. Več deset tisoč asinhronih operacij, ki se izvajajo hkrati, bo imelo veliko manj stroškov kot deset tisoč niti.
  • Struktura async kode olajša sklepanje o tem, kje naloge poberejo in končajo. To pomeni, da podatkovne dirke in varnost niti niso manj pomembni. Ker se vsa opravila v zanki dogodkov asinhronizacije izvajajo v eni niti, je Pythonu (in razvijalcu) lažje serializirati način dostopa do predmetov v pomnilniku.
  • Async operacije lahko prekličete in z njimi manipulirate hitreje kot niti. The Naloga predmet, iz katerega se vrnemo asyncio.create_task () nam ponuja priročen način za to.

Po drugi strani je večprocesorska obdelava v Pythonu najboljša za opravila, ki so močno vezana na CPU in ne na I / O. Async dejansko deluje z roko v roki z večprocesorsko obdelavo, kot jo lahko uporabite asyncio.run_in_executor () za prenos procesov z intenzivnim procesorjem v procesno področje iz osrednjega procesa, ne da bi ta osrednji proces blokiral.

Naslednji koraki s Python async

Najboljše, kar morate najprej narediti, je, da sestavite nekaj preprostih asinhronskih aplikacij sami. Zdaj je veliko dobrih primerov, ko je bilo asinhrono programiranje v Pythonu podvrženo nekaj različicam in se je moralo nekaj let umiriti in širše uporabljati. Uradna dokumentacija za asincio je vredno prebrati, da vidite, kaj ponuja, tudi če ne nameravate izkoristiti vseh njegovih funkcij.

Prav tako lahko raziščete naraščajoče število knjižnic in vmesne programske opreme, ki jih poganja asinhronski sistem, od katerih mnogi ponujajo asinhrone, neblokirajoče različice spojnikov baz podatkov, omrežnih protokolov in podobno. The aio-libs repozitorij ima nekaj ključnih, kot je aiohittp knjižnica za spletni dostop. Prav tako je vredno poiskati indeks paketov Python za knjižnice z asinh ključna beseda. Pri nečem podobnem asinhronem programiranju je najboljši način učenja, da vidimo, kako so ga drugi uporabili.

$config[zx-auto] not found$config[zx-overlay] not found