8.12. Async context manager¶
Ikhtisar Python memperkenalkan context manager -- objek yang dikendalikan oleh blok with, dengan __enter__ berjalan saat masuk dan __exit__ berjalan saat keluar tidak peduli bagaimana blok berakhir. Async context manager adalah ide yang sama yang dipindahkan ke asyncio: __aenter__ dan __aexit__ adalah coroutine, sehingga setup atau pembersihan dapat melakukan await. Blok yang mengendalikannya adalah async with.
Kita sudah menggunakannya. asyncio.Lock adalah async context manager; halaman lock menggunakannya sebagai async with bus_lock: .... Halaman ini membahas cara menulis satu untuk sumber daya aplikasi sendiri.
8.12.1. Kapan menulis satu¶
Ketika aplikasi memiliki sumber daya yang membutuhkan setup dan pembongkaran yang berpasangan, dan setidaknya satu dari sisi tersebut harus melakukan await. Koneksi jaringan, sensor yang membutuhkan penundaan stabilisasi setelah konfigurasi, apa pun yang mengunci sesuatu saat masuk dan membukanya saat keluar. Bentuk with sinkron biasa tidak berlaku karena __enter__ dan __exit__-nya tidak bisa berupa coroutine.
8.12.2. Dua metode¶
async def __aenter__(self)berjalan saat blok dimasuki. Apa pun yang dikembalikannya adalah yang diikat oleh klausa opsionalas namedariasync with. Mengembalikanselfadalah bentuk paling umum, tetapi nilai apa pun bisa.async def __aexit__(self, exc_type, exc, tb)berjalan saat blok keluar.exc_typeadalahNonepada keluar normal; pada pengecualian (atau pembatalan) itu adalah kelas pengecualian, danexcadalah instance-nya. Mengembalikan nilai truthy memberi tahu Python bahwa pengecualian telah ditangani dan tidak perlu merambat. MengembalikanNone(kasus biasa) membiarkan pengecualian terus ke atas rantai panggilan setelah pembersihan selesai.
8.12.3. Contoh yang dikerjakan¶
Pembungkus sorotan yang menyalakan LED untuk isi blok, dengan penundaan stabilisasi singkat agar pencahayaan stabil sebelum pengambilan gambar terjadi, dan mematikan LED kembali saat keluar:
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())
Saat blok dimasuki, __aenter__ berjalan: LED menyala, penundaan 50 ms await menghasilkan kontrol ke loop sehingga coroutine lain dapat membuat kemajuan sementara itu, dan isi blok dimulai setelah penantian selesai. Saat blok berakhir -- baik keluar normal, pengecualian, maupun pembatalan -- __aexit__ berjalan dan LED mati kembali. Pembersihan berjalan di setiap kasus; itulah jaminan yang diberikan 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.