8.12. Asenkron bağlam yöneticileri

Python’a Genel Bakış bağlam yöneticilerini tanıttı – with bloklarının sürdüğü, girişte __enter__ çalışan ve blok nasıl biterse bitsin çıkışta __exit__ çalışan nesneler. Asenkron bağlam yöneticileri, asyncio’ya taşınmış aynı fikirdir: __aenter__ ve __aexit__ eşyordamlardır, dolayısıyla kurulum veya temizlik bir şeyi await edebilir. Onları süren blok async with‘tir.

Zaten birini kullandık. asyncio.Lock bir asenkron bağlam yöneticisidir; kilitler sayfası onu async with bus_lock: ... olarak kullandı. Bu sayfa, bir uygulamanın kendi kaynağı için böyle bir tane yazmakla ilgilidir.

8.12.1. Ne zaman yazılmalı

Uygulamanın eşleştirilmiş kurulum ve sökme gerektiren bir kaynağı olduğunda ve bu taraflardan en az birinin bir şeyi await etmesi gerektiğinde. Ağ bağlantıları, yapılandırmadan sonra bir oturma gecikmesine ihtiyaç duyan sensörler, girişte bir şeyi kilitleyip çıkışta kilidini açan herhangi bir şey. Düz eşzamanlı with biçimi geçerli değildir çünkü __enter__ ve __exit__‘i eşyordam olamaz.

8.12.2. İki yöntem

  • async def __aenter__(self), bloğa girildiğinde çalışır. Döndürdüğü şey, async with‘in isteğe bağlı as name yan tümcesinin bağlandığı şeydir. self döndürmek en yaygın yapıdır, ancak herhangi bir değer işe yarar.

  • async def __aexit__(self, exc_type, exc, tb), bloktan çıkıldığında çalışır. exc_type, normal bir çıkışta None‘dır; bir istisnada (veya bir iptalde) istisnanın sınıfıdır ve exc örnektir. Doğru bir değer döndürmek, Python’a istisnanın işlendiğini ve yayılmaması gerektiğini söyler. None döndürmek (her zamanki durum), temizlik çalıştıktan sonra istisnanın çağrı zincirinde yukarı doğru devam etmesine izin verir.

8.12.3. Çalışan bir örnek

Bloğun gövdesi için bir LED’i yakan, herhangi bir yakalama gerçekleşmeden önce aydınlatmanın kararlı olması için kısa bir oturma gecikmesiyle birlikte, ve çıkışta LED’i yeniden söndüren bir spot ışığı sarmalayıcısı:

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())

Bloğa girildiğinde __aenter__ çalışır: LED yanar, 50 ms’lik oturma await‘i, bu arada diğer eşyordamların ilerleme kaydedebilmesi için döngüye denetim verir ve bekleme tamamlandığında blok gövdesi başlar. Blok bittiğinde – normal bir çıkışta, bir istisnada veya iptalde – __aexit__ çalışır ve LED yeniden söner. Temizlik her durumda çalışır; bu, async with‘in sağladığı garantidir.

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.