Programmering

Sådan bruges asyncio i Python

Pythons asynkrone programmeringsfunktionalitet, eller kort sagt async, giver dig mulighed for at skrive programmer, der får mere arbejde udført ved ikke at vente på, at uafhængige opgaver er færdige. Det asyncio bibliotek inkluderet i Python giver dig værktøjerne til at bruge async til behandling af disk eller netværk I / O uden at lade alt andet vente.

asyncio giver to slags API'er til håndtering af asynkrone operationer:højt niveau oglavt niveau. API'er på højt niveau er de mest nyttige, og de kan anvendes til det bredeste udvalg af applikationer. API'erne på lavt niveau er kraftfulde, men også komplekse og bruges sjældnere.

Vi koncentrerer os om API'er på højt niveau i denne artikel. I afsnittene nedenfor gennemgår vi de mest anvendte API'er på højt niveau iasyncio, og vise, hvordan de kan bruges til almindelige operationer, der involverer asynkrone opgaver.

Hvis du er helt ny inden for async i Python, eller du kan bruge en opfriskning til, hvordan det fungerer, skal du læse min introduktion til Python async, før du dykker ind her.

Kør coroutines og opgaver i Python

Naturligvis den mest almindelige anvendelse til asyncio er at køre de asynkrone dele af dit Python-script. Dette betyder at lære at arbejde med coroutines og opgaver.

Pythons async-komponenter, herunder coroutines og opgaver, kan kun bruges med andre async-komponenter og ikke med konventionel synkron Python, så du har brug forasyncio for at bygge bro over kløften. For at gøre dette skal du brugeasyncio.run fungere:

importer asyncio

async def hoved ():

udskrive ("Venter 5 sekunder.")

for _ inden for rækkevidde (5):

afventer asyncio.sleep (1)

Print (".")

print ("Færdig ventetid.")

asyncio.run (main ())

Dette kørerhoved ()sammen med eventuelle coroutineshoved () fyres af og venter på, at et resultat vender tilbage.

Som hovedregel skal et Python-program kun have et.løb() erklæring, ligesom et Python-program kun skal have enhoved () fungere. Async, hvis det bruges uforsigtigt, kan gøre kontrolprogrammet for et program svært at læse. At have et enkelt indgangspunkt til et programs async-kode forhindrer ting i at blive hår.

Async-funktioner kan også planlægges somopgavereller genstande, der omslutter coroutines og hjælper med at køre dem.

async def min_opgave ():

gør noget()

opgave = asyncio.create_task (min_opgave ())

min_opgave () køres derefter i hændelsesløkken med resultaterne gemt iopgave.

Hvis du kun har en opgave, du vil få resultater fra, kan du brugeasyncio.wait_for (opgave) at vente på, at opgaven er færdig, og brug dereftertask.result () for at hente resultatet. Men hvis du har planlagt et antal opgaver, der skal udføres, og du vil vente påalle af dem til at afslutte, brugeasyncio.wait ([task1, task2]) at samle resultaterne. (Bemærk, at du kan indstille en timeout for operationerne, hvis du ikke vil have dem til at løbe forbi en bestemt tidsperiode.)

Administrer en asynkroniseret hændelsessløjfe i Python

En anden almindelig anvendelse tilasyncio er at styre asyncbegivenhedssløjfe. Begivenhedssløjfen er et objekt, der kører asynkroniseringsfunktioner og tilbagekald; det oprettes automatisk, når du brugerasyncio.run (). Du vil generelt kun bruge en asynkroniseringshændelsesløkke pr. Program igen for at holde tingene håndterbare.

Hvis du skriver mere avanceret software, f.eks. En server, har du brug for adgang på lavere niveau til begivenhedssløjfen. Til dette formål kan du "løfte hætten" og arbejde direkte med begivenhedsløkkens indvendige dele. Men for enkle job behøver du ikke.

Læs og skriv data med streams i Python

De bedste scenarier for async er langvarige netværksoperationer, hvor applikationen muligvis blokerer for at vente på, at en anden ressource returnerer et resultat. Til dette formålasyncio tilbyder streams, som er mekanismer på højt niveau til udførelse af netværk I / O. Dette inkluderer at fungere som en server til netværksanmodninger.

asyncio bruger to klasser,StreamReader ogStreamWriter, at læse og skrive fra netværket på et højt niveau. Hvis du vil læse fra netværket, skal du bruge detasyncio.open_connection () for at åbne forbindelsen. Denne funktion returnerer en tuple påStreamReader ogStreamWriter objekter, og du ville bruge.Læs() og.skrive() metoder på hver til at kommunikere.

Brug for at modtage forbindelser fra eksterne værterasyncio.start_server (). Det asyncio.start_server () funktion tager som et argument en tilbagekaldsfunktion,klient_forbundet_cb, som kaldes, når den modtager en anmodning. Denne tilbagekaldsfunktion tager forekomster afStreamReader og StreamWriter som argumenter, så du kan håndtere læse / skrive logikken for serveren. (Se her for et eksempel på en simpel HTTP-server, der brugerasyncio-kørtaiohttp bibliotek.)

Synkroniser opgaver i Python

Asynkrone opgaver har tendens til at køre isoleret, men nogle gange vil du have dem til at kommunikere med hinanden.asyncio giver køer og flere andre mekanismer til synkronisering mellem opgaver:

  • Køerasyncio køer tillader asynkrone funktioner at oprette Python-objekter, der skal forbruges af andre async-funktioner - for eksempel at distribuere arbejdsbelastninger mellem forskellige slags funktioner baseret på deres adfærd.
  • Primitiver til synkronisering: Låse, begivenheder, betingelser og semaforer i asyncio arbejde som deres konventionelle Python-kolleger.

En ting at huske på alle disse metoder er, at de erikke trådsikker. Dette er ikke et problem for asynkroniseringsopgaver, der kører i samme hændelsesløkke. Men hvis du prøver at dele oplysninger med opgaver i en anden hændelsesløkke, OS-tråd eller proces, skal du brugetrådning modulet og dets objekter til at gøre det.

Yderligere, hvis du villancering coroutines på tværs af trådgrænser, brugasyncio.run_coroutine_threadsafe () funktion, og videregive hændelsesløkken for at bruge den som en parameter.

Sæt en coroutine på pause i Python

En anden almindelig anvendelse afasyncio, og en underdiskuteret, venter på en vilkårlig tid inde i en coroutine. Du kan ikke brugetime.sleep () for dette, ellers blokerer du hele programmet. Brug i stedetasyncio.sleep (), som gør det muligt for andre coroutines at køre.

Brug asynkronisering på lavere niveau i Python

Endelig, hvis du mener, at den app, du bygger, muligvis kræver asyncioKomponenter på lavere niveau, se dig omkring, før du begynder at kode: Der er en god chance for, at nogen allerede har bygget et asynkroniseret Python-bibliotek, der gør, hvad du har brug for.

For eksempel, hvis du har brug for asynkroniseret DNS-forespørgsel, skal du kontrollereaiodns bibliotek, og for asynkroniserede SSH-sessioner er derasyncSSH. Søg i PyPI efter nøgleordet "async" (plus andre opgaverelaterede nøgleord), eller tjek den håndkurerede Awesome Asyncio-liste for idéer.