8.12. Aszinkron környezetkezelők¶
A Python áttekintés bemutatta a környezetkezelőket – azokat az objektumokat, amelyeket a with blokkok vezérelnek, ahol az __enter__ a belépéskor fut, az __exit__ pedig a kilépéskor, függetlenül attól, hogyan ér véget a blokk. Az aszinkron környezetkezelők ugyanaz az ötlet áthelyezve az asyncio világába: az __aenter__ és az __aexit__ korutinok, így a beállítás vagy a tisztítás await-tel várhat valamire. Az őket vezérlő blokk az async with.
Egyet már használtunk is. Az asyncio.Lock egy aszinkron környezetkezelő; a zárak oldal async with bus_lock: ... formában használta. Ez az oldal arról szól, hogyan írjunk egyet egy alkalmazás saját erőforrásához.
8.12.1. Mikor írjunk egyet¶
Amikor az alkalmazásnak van egy erőforrása, amely párosított beállítást és lebontást igényel, és legalább az egyik oldalnak await-tel várnia kell valamire. Hálózati kapcsolatok, érzékelők, amelyeknek a konfigurálás után stabilizálódási késleltetés kell, bármi, ami belépéskor lezár valamit és kilépéskor feloldja. Az egyszerű szinkron with forma nem alkalmazható, mert az __enter__ és az __exit__ nem lehet korutin.
8.12.2. A két metódus¶
Az
async def __aenter__(self)akkor fut, amikor belépünk a blokkba. Amit visszaad, azt köti azasync withopcionálisas nameága. Aselfvisszaadása a leggyakoribb forma, de bármilyen érték működik.Az
async def __aexit__(self, exc_type, exc, tb)akkor fut, amikor kilépünk a blokkból. Azexc_typeNonenormál kilépéskor; kivétel (vagy megszakítás) esetén ez a kivétel osztálya, azexcpedig a példány. Egy igaz érték visszaadása azt mondja a Pythonnak, hogy a kivétel kezelve lett, és nem szabad továbbterjednie. ANonevisszaadása (a szokásos eset) hagyja, hogy a kivétel a tisztítás lefutása után tovább terjedjen a hívási láncon.
8.12.3. Egy kidolgozott példa¶
Egy reflektor-burkoló, amely a blokk törzsének idejére bekapcsol egy LED-et, egy rövid stabilizálódási késleltetéssel, hogy a megvilágítás stabil legyen, mielőtt bármilyen felvétel megtörténne, majd a kilépéskor ismét kikapcsolja a LED-et:
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())
Amikor belépünk a blokkba, lefut az __aenter__: a LED bekapcsol, az 50 ms-os stabilizálódási await átadja a vezérlést a huroknak, hogy más korutinok közben haladhassanak, és a blokk törzse a várakozás befejeztével indul el. Amikor a blokk véget ér – normál kilépéskor, kivétel esetén, vagy megszakításkor –, lefut az __aexit__, és a LED ismét kikapcsol. A tisztítás minden esetben lefut; ezt a garanciát nyújtja az async with.
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.