8.12. Asinkroni upravitelji konteksta¶
Pregled Pythona predstavio je upravitelje konteksta – objekte kojima upravljaju with blokovi, gdje se __enter__ izvršava na ulasku, a __exit__ na izlasku, bez obzira na to kako blok završi. Asinkroni upravitelji konteksta ista su zamisao prenesena u asyncio: __aenter__ i __aexit__ su korutine, pa postavljanje ili čišćenje mogu nešto awaitati. Blok koji njima upravlja je async with.
Jednog smo već koristili. asyncio.Lock je asinkroni upravitelj konteksta; stranica brave ga je koristila kao async with bus_lock: .... Ova stranica govori o pisanju jednog za vlastiti resurs aplikacije.
8.12.1. Kada napisati svoj¶
Kad aplikacija ima resurs kojem je potrebno upareno postavljanje i raščišćavanje, a barem jedna od tih strana mora nešto awaitati. Mrežne veze, senzori kojima je potrebna odgoda za smirivanje nakon konfiguracije, sve što nešto zaključa pri ulasku i otključa pri izlasku. Obični sinkroni oblik with ne primjenjuje se jer njegovi __enter__ i __exit__ ne mogu biti korutine.
8.12.2. Dvije metode¶
async def __aenter__(self)izvršava se kad se uđe u blok. Što god vrati, to je ono na što se veže neobavezna klauzulaas nameodasync with. Vraćanjeselfje najčešći oblik, ali svaka vrijednost je u redu.async def __aexit__(self, exc_type, exc, tb)izvršava se kad se izađe iz bloka.exc_typejeNonepri normalnom izlasku; pri iznimci (ili otkazivanju) to je klasa iznimke, aexcje instanca. Vraćanje vrijednosti koja je istinita govori Pythonu da je iznimka obrađena i da se ne treba propagirati. VraćanjeNone(uobičajen slučaj) pušta iznimku da nastavi uz lanac poziva nakon što se čišćenje izvrši.
8.12.3. Razrađen primjer¶
Omotač reflektora koji uključuje LED-icu za tijelo bloka, s kratkom odgodom za smirivanje kako bi osvjetljenje bilo stabilno prije nego što se ikakvo snimanje dogodi, te ponovno isključuje LED-icu na izlasku:
import asyncio
from machine import LED
class Spotlight:
def __init__(self, led):
self._led = led
async def __aenter__(self):
self._led.on()
await asyncio.sleep_ms(50)
return self
async def __aexit__(self, exc_type, exc, tb):
self._led.off()
async def main():
led = LED("LED_WHITE")
async with Spotlight(led):
# work that benefits from steady illumination
await asyncio.sleep_ms(200)
asyncio.run(main())
Kad se uđe u blok, __aenter__ se izvršava: LED-ica se uključuje, await za 50 ms smirivanja predaje kontrolu petlji kako bi druge korutine u međuvremenu mogle napredovati, a tijelo bloka započinje čim čekanje završi. Kad blok završi – pri normalnom izlasku, pri iznimci ili pri otkazivanju – __aexit__ se izvršava i LED-ica se ponovno isključuje. Čišćenje se izvršava u svakom slučaju; to je jamstvo koje async with pruža.
The frame capture page
shows how to make csi.CSI.snapshot() await-friendly; once that wrapper is in hand, the body of an
async with Spotlight(led): block would typically be a
capture loop running under the steady illumination.