Pythons asynkrone programmeringsfunksjonalitet, eller forkortelse async, lar deg skrive programmer som får mer arbeid gjort ved ikke å vente på at uavhengige oppgaver skal fullføres. De asyncio
biblioteket som følger med Python, gir deg verktøyene for å bruke async for behandling av disk eller nettverks I / O uten å få alt annet til å vente.
asyncio
gir to typer APIer for å håndtere asynkrone operasjoner:høy level oglavt nivå. API-er på høyt nivå er de mest nyttige, og de kan brukes i det bredeste spekteret av applikasjoner. API-er på lavt nivå er kraftige, men også komplekse, og brukes sjeldnere.
Vi konsentrerer oss om API-er på høyt nivå i denne artikkelen. I avsnittene nedenfor går vi gjennom de mest brukte API-ene på høyt nivå iasyncio
, og viser hvordan de kan brukes til vanlige operasjoner som involverer asynkrone oppgaver.
Hvis du er helt ny innen asynkronisering i Python, eller du kan bruke en forfriskning på hvordan det fungerer, kan du lese introduksjonen min til Python async før du dykker inn her.
Kjør coroutines og oppgaver i Python
Naturligvis den vanligste bruken for asyncio
er å kjøre de asynkrone delene av Python-skriptet. Dette betyr å lære å jobbe med coroutines og oppgaver.
Pythons async-komponenter, inkludert coroutines og oppgaver, kan bare brukes med andre async-komponenter, og ikke med konvensjonell synkron Python, så du trengerasyncio
for å bygge bro over gapet. For å gjøre dette bruker duasyncio.run
funksjon:
importer asyncioasync def hoved ():
utskrift ("Venter i 5 sekunder.")
for _ innen rekkevidde (5):
venter på asyncio.sleep (1)
skrive ut (".")
utskrift ("Ferdig ventet.")
asyncio.run (main ())
Dette gårhoved()
, sammen med noen coroutineshoved()
fyrer av og venter på at resultatet skal komme tilbake.
Som en generell regel bør et Python-program bare ha ett.løpe()
uttalelse, akkurat som et Python-program bare skal ha enhoved()
funksjon. Async, hvis det brukes uforsiktig, kan gjøre kontrollflyten til et program vanskelig å lese. Å ha et enkelt inngangspunkt til programmets asynkroniseringskode hindrer at ting blir hårete.
Async-funksjoner kan også planlegges somoppgaver, eller gjenstander som pakker coroutines og hjelper med å kjøre dem.
async def min_oppgave ():gjør noe()
oppgave = asyncio.create_task (min_oppgave ())
min_oppgave ()
kjøres deretter i hendelsessløyfen, med resultatene lagret ioppgave
.
Hvis du bare har en oppgave du vil få resultater fra, kan du brukeasyncio.wait_for (oppgave)
å vente til oppgaven er ferdig, og bruk derettertask.result ()
for å hente resultatet. Men hvis du har planlagt en rekke oppgaver som skal utføres, og du vil vente påalle av dem for å fullføre, brukeasyncio.wait ([oppgave1, oppgave2])
for å samle resultatene. (Merk at du kan angi en tidsavbrudd for operasjonene hvis du ikke vil at de skal kjøre forbi en viss tidsperiode.)
Administrer en asynkroniseringshendelsessløyfe i Python
En annen vanlig bruk forasyncio
er å administrere asynkroniseringenhendelsessløyfe. Hendelsessløyfen er et objekt som kjører asynkroniseringsfunksjoner og tilbakeringing; den opprettes automatisk når du brukerasyncio.run ()
. Du vil vanligvis bare bruke en asynkroniseringshendelsessløyfe per program, igjen for å holde ting håndterbart.
Hvis du skriver mer avansert programvare, for eksempel en server, trenger du tilgang på lavere nivå til hendelsessløyfen. For å oppnå dette kan du "løfte hetten" og jobbe direkte med hendelsessløyfens indre. Men for enkle jobber trenger du ikke.
Les og skriv data med strømmer i Python
De beste scenariene for async er langvarige nettverksoperasjoner, der applikasjonen kan blokkere å vente på at en annen ressurs skal returnere et resultat. Til den slutten,asyncio
tilbyr streams, som er mekanismer på høyt nivå for å utføre nettverks I / O. Dette inkluderer å fungere som en server for nettverksforespørsler.
asyncio
bruker to klasser,StreamReader
ogStreamWriter
, å lese og skrive fra nettverket på høyt nivå. Hvis du vil lese fra nettverket, vil du brukeasyncio.open_connection ()
for å åpne forbindelsen. Den funksjonen returnerer en tusenvis avStreamReader
ogStreamWriter
gjenstander, og du vil bruke.lese()
og.skrive()
metoder på hver for å kommunisere.
Bruk for å motta tilkoblinger fra eksterne verterasyncio.start_server ()
. De asyncio.start_server ()
funksjon tar som et argument en tilbakeringingsfunksjon,client_connected_cb
, som kalles når den mottar en forespørsel. Den tilbakeringingsfunksjonen tar forekomster avStreamReader
og StreamWriter
som argumenter, slik at du kan håndtere lese- / skrivelogikken for serveren. (Se her for et eksempel på en enkel HTTP-server som brukerasyncio
-drevetaiohttp
bibliotek.)
Synkroniser oppgaver i Python
Asynkrone oppgaver har en tendens til å løpe isolert, men noen ganger vil du at de skal kommunisere med hverandre.asyncio
gir køer og flere andre mekanismer for synkronisering mellom oppgaver:
- Køer:
asyncio
køer tillater asynkrone funksjoner å stille opp Python-objekter som skal konsumeres av andre async-funksjoner - for eksempel å distribuere arbeidsmengder mellom forskjellige typer funksjoner basert på deres atferd. - Primitiver for synkronisering: Låser, hendelser, forhold og semaforer i
asyncio
fungerer som deres konvensjonelle Python-kolleger.
En ting å huske på om alle disse metodene er at de erikke trådsikker. Dette er ikke et problem for asynkroniseringsoppgaver som kjøres i samme hendelsessløyfe. Men hvis du prøver å dele informasjon med oppgaver i en annen hendelsessløyfe, OS-tråd eller prosess, må du brukegjenging
modulen og dens objekter for å gjøre det.
Videre, hvis du villansering coroutines over trådgrenser, brukasyncio.run_coroutine_threadsafe ()
funksjon, og pass hendelsessløyfen for å bruke den som parameter.
Sett en coroutine på pause i Python
En annen vanlig bruk avasyncio
, og en underdiskutert, venter på en vilkårlig tid inne i en coroutine. Du kan ikke bruketime.sleep ()
for dette, ellers blokkerer du hele programmet. Bruk i stedetasyncio.sleep ()
, som gjør at andre coroutines kan fortsette å løpe.
Bruk asynkronisering på lavere nivå i Python
Til slutt, hvis du tror at appen du bygger kan kreve asyncio
Komponenter på lavere nivå, ta en titt rundt før du begynner å kode: Det er stor sjanse for at noen allerede har bygget et asynkronisert Python-bibliotek som gjør det du trenger.
For eksempel, hvis du trenger asynkronisering av DNS-spørring, sjekkaiodns
bibliotek, og for asynkroniserte SSH-økter, er detasyncSSH
. Søk i PyPI etter nøkkelordet “async” (pluss andre oppgaverelaterte nøkkelord), eller sjekk den håndkurerte Awesome Asyncio-listen for ideer.