8.12. Asynkroniset kontekstinhallitsijat¶
Python Overview esitteli kontekstinhallitsijat – objektit, joita with-lohkot ohjaavat, ja joiden __enter__ suoritetaan sisäänmentäessä ja __exit__ suoritetaan uloslähdettäessä riippumatta siitä, miten lohko päättyy. Asynkroniset kontekstinhallitsijat ovat sama idea siirrettynä asyncioon: __aenter__ ja __aexit__ ovat korutiineja, joten alustus tai siivous voi awaitttaa jotain. Lohko, joka niitä ohjaa, on async with.
Olemme jo käyttäneet yhtä. asyncio.Lock on asynkroninen kontekstinhallitsija; locks -sivu käytti sitä muodossa async with bus_lock: .... Tämä sivu käsittelee sellaisen kirjoittamista sovelluksen omalle resurssille.
8.12.1. Milloin sellainen kirjoitetaan¶
Kun sovelluksella on resurssi, joka tarvitsee parittaista alustusta ja purkua, ja vähintään toisen näistä puolista on awaitttava jotain. Verkkoyhteydet, sensorit jotka tarvitsevat asettumisviiveen konfiguroinnin jälkeen, kaikki mikä lukitsee jotain sisäänmentäessä ja avaa lukituksen uloslähdettäessä. Tavallinen synkroninen with-muoto ei sovellu, koska sen __enter__ ja __exit__ eivät voi olla korutiineja.
8.12.2. Kaksi metodia¶
async def __aenter__(self)suoritetaan, kun lohkoon mennään. Mitä tahansa se palauttaa, on se, mihinasync with-lauseen valinnainenas name-osa sidotaan.self-arvon palauttaminen on yleisin muoto, mutta mikä tahansa arvo toimii.async def __aexit__(self, exc_type, exc, tb)suoritetaan, kun lohkosta poistutaan.exc_typeonNonenormaalissa poistumisessa; poikkeuksen (tai perumisen) yhteydessä se on poikkeuksen luokka, jaexcon instanssi. Toden kaltaisen arvon palauttaminen kertoo Pythonille, että poikkeus on käsitelty eikä sen pitäisi edetä.None-arvon palauttaminen (tavanomainen tapaus) antaa poikkeuksen jatkaa ylöspäin kutsuketjussa siivouksen suorittamisen jälkeen.
8.12.3. Työstetty esimerkki¶
Kohdevalokääre, joka sytyttää LEDin lohkon rungon ajaksi lyhyellä asettumisviiveellä, jotta valaistus on vakaa ennen kaappauksia, ja sammuttaa LEDin taas uloslähdettäessä:
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())
Kun lohkoon mennään, __aenter__ suoritetaan: LED syttyy, 50 ms:n asettumis-await luovuttaa vuoron silmukalle, jotta muut korutiinit voivat edetä sillä välin, ja lohkon runko alkaa, kun odotus on valmis. Kun lohko päättyy – normaalissa poistumisessa, poikkeuksessa tai perumisessa – __aexit__ suoritetaan ja LED sammuu jälleen. Siivous suoritetaan joka tapauksessa; se on takuu, jonka async with tarjoaa.
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.