8.2. Korutiinit ja tehtävät¶
Korutiinit ovat se työyksikkö, josta asyncio-ohjelma rakentuu; tehtävät ovat se tapa, jolla sovellus ajaa useita korutiineja rinnakkain.
8.2.1. Korutiinit¶
Korutiini on funktio, joka on määritelty async def -määreellä:
import asyncio
async def heartbeat(interval_ms):
while True:
print("tick")
await asyncio.sleep_ms(interval_ms)
Runko näyttää tavalliselta funktiolta yhtä lisäainesta lukuun ottamatta: await. Aina kun korutiinin on odotettava jotain – unta, verkkolukua, asetettavaa tapahtumaa – se awaitaa lauseketta, joka osaa keskeyttää korutiinin, kunnes se mitä se odottaa on valmis. Jokaisessa await -kohdassa korutiini luovuttaa hallinnan takaisin asynciolle; asyncio jatkaa sitä samasta kohdasta heti kun odotettu operaatio on valmistunut.
Asyncio-moduuli toimittaa kaksi unta:
asyncio.sleep()– argumentti sekunteina, hyväksyy liukuluvun.asyncio.sleep_ms()– argumentti millisekunteina, ottaa kokonaisluvun. MicroPython-laajennus; yleensä oikea valinta kameralla, koska laiteohjelmiston ajoitusparametrit ovat millisekunnin muotoisia.
Pelkkä async def ei tee mitään itsekseen. Kutsu heartbeat(500) ei suorita runkoa; se palauttaa korutiiniobjektin, jonka asyncion on ajoitettava. Yksinkertaisin tapa ajoittaa sellainen on asyncio.run()
asyncio.run(heartbeat(500))
asyncio.run() käynnistää tapahtumasilmukan, ajoittaa sille annetun korutiinin ylimmän tason aloituspisteeksi, ohjaa silmukkaa kunnes kyseinen korutiini palaa, ja sitten purkaa silmukan. Yhden korutiinin tapauksessa siinä on koko ohjelma. Useamman korutiinin tapauksessa sovellus turvautuu tehtäviin.
8.2.2. Tehtävät¶
Tehtävä on asyncion kääre korutiinin ympärillä, joka sanoo ajoita tämä rinnakkain nykyisen kanssa ja anna minun jatkaa eteenpäin. asyncio.create_task() luo sellaisen ja palauttaa Task -objektin, joka edustaa ajoitettua työtä:
task = asyncio.create_task(heartbeat("fast", 100))
Korutiini on nyt silmukan ajolistalla; kutsuja ei ole odottanut sitä. Palautettu Task on se kahva, jota kutsuja käyttää myöhemmin vuorovaikuttaakseen kyseisen käynnissä olevan työn kanssa.
Kun sovelluksella on kahva, se voi tehdä sillä kolme asiaa:
Odottaa tehtävän valmistumista.
Taskon itsessään awaitattava.result = await taskkeskeyttää nykyisen korutiinin, kunnestask:n korutiini palaa, ja jatkaa sitten sillä mitä korutiini palautti (tai nostaa uudelleen sen mitä se nosti).Peruuttaa tehtävän.
task.cancel()ajoittaaasyncio.CancelledError-poikkeuksen nostettavaksi tehtävän korutiinin sisällä sen seuraavassaawait-kohdassa, antaen sille mahdollisuuden ajaa siivouskoodiafinally-lohkossa. Sivu aikakatkaisut ja peruutus käsittelee yksityiskohdat.Tunnistaa sen myöhemmin.
asyncio.current_task()palauttaaTask-objektin sille korutiinille, joka on parhaillaan käynnissä. Useimmat skriptit eivät koskaan kutsu sitä; se esiintyy instrumentoinnissa ja poikkeuskäsittelijöissä.
Skriptin ei tarvitse ottaa kahvaa talteen joka kerta. Kertakäyttöiset taustatehtävät, jotka sovellus käynnistää ja jättää käymään, voivat hylätä paluuarvon – silmukka ajoittaa ne silti:
import asyncio
async def heartbeat(name, interval_ms):
while True:
print(name)
await asyncio.sleep_ms(interval_ms)
async def main():
asyncio.create_task(heartbeat("fast", 100))
asyncio.create_task(heartbeat("slow", 500))
await asyncio.sleep(5)
asyncio.run(main())
Kaksi create_task -kutsua ajoittavat molemmat sykkeet odottamatta kumpaakaan niistä. Hallinta palaa välittömästi main:lle, joka sitten awaitaa viiden sekunnin unta. Sen nukkuessa kaksi sykintätehtävää etenevät; silmukka kiertää sen tehtävän läpi, joka on valmis suoritettavaksi. Viiden sekunnin jälkeen main palaa, silmukka purkaa kaikki tehtävät, jotka ovat vielä elossa, ja asyncio.run() palaa kutsujalle.
Ota kahva talteen aina kun sovellus todella tarvitsee jonkin yllä olevista kolmesta operaatiosta. Käytännössä se tarkoittaa lähes aina, koska sovelluksen siisti sammuttaminen tarkoittaa sen synnyttämien taustatehtävien peruuttamista – peruutussivu käsittelee tämän kaavan.
8.2.3. Kahden rivin sääntö¶
Minimaalinen asyncio-ohjelma on ne kaksi riviä, joihin yllä olevat esimerkit päättyvät:
async def main():
...
asyncio.run(main())
Kaikki muu – tehtävät, jotka sovellus luo, primitiivit, joilla se koordinoi niitä, virrat, jotka se avaa – tapahtuu main:n sisällä (ja niiden korutiinien sisällä, jotka main synnyttää). Kun skripti kasvaa kameran klassista while True: csi0.snapshot() -silmukkaa suuremmaksi, vastaus ei ole kutsua asyncio.run() -funktiota useassa paikassa; se on taittaa uusi työ main:iin lisää tehtävinä.