8.12. Asynchronní kontextové manažery¶
Přehled Pythonu představil kontextové manažery – objekty, které řídí bloky with, kde se __enter__ provádí při vstupu a __exit__ při výstupu bez ohledu na to, jak blok skončí. Asynchronní kontextové manažery jsou tatáž myšlenka přenesená do asyncio: __aenter__ a __aexit__ jsou korutiny, takže příprava nebo úklid mohou na něco awaitovat. Blok, který je řídí, je async with.
Jeden jsme již použili. asyncio.Lock je asynchronní kontextový manažer; stránka o zámcích jej použila jako async with bus_lock: .... Tato stránka je o napsání vlastního pro prostředek aplikace.
8.12.1. Kdy si jej napsat¶
Když má aplikace prostředek, který potřebuje párovou přípravu a uvolnění, a alespoň jedna z těchto stran musí na něco awaitovat. Síťová spojení, senzory, které po konfiguraci potřebují čas na ustálení, cokoli, co něco zamkne při vstupu a odemkne při výstupu. Prostá synchronní podoba with se nepoužije, protože její __enter__ a __exit__ nemohou být korutinami.
8.12.2. Dvě metody¶
async def __aenter__(self)se spustí při vstupu do bloku. Cokoli vrátí, je to, k čemu se naváže volitelná klauzuleas nameuasync with. Vraceníselfje nejběžnější podobou, ale funguje libovolná hodnota.async def __aexit__(self, exc_type, exc, tb)se spustí při výstupu z bloku.exc_typejeNonepři normálním výstupu; při výjimce (nebo zrušení) je to třída výjimky aexcje instance. Vrácení pravdivé hodnoty řekne Pythonu, že výjimka byla ošetřena a neměla by se propagovat. VráceníNone(obvyklý případ) nechá výjimku po proběhnutí úklidu pokračovat nahoru řetězcem volání.
8.12.3. Rozpracovaný příklad¶
Wrapper reflektoru, který po dobu těla bloku rozsvítí LED, s krátkým časem na ustálení, aby bylo osvětlení před jakýmkoli snímáním stabilní, a při výstupu LED opět zhasne:
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())
Při vstupu do bloku se spustí __aenter__: LED se rozsvítí, 50ms await na ustálení předá řízení smyčce, takže mezitím mohou postupovat ostatní korutiny, a tělo bloku se spustí, jakmile čekání skončí. Když blok skončí – při normálním výstupu, při výjimce nebo při zrušení – spustí se __aexit__ a LED se opět zhasne. Úklid proběhne v každém případě; to je záruka, kterou async with poskytuje.
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.