8.12. 비동기 컨텍스트 매니저

Python 개요 에서 컨텍스트 매니저를 소개했습니다 – with 블록이 구동하는 객체로, 진입 시 __enter__ 가 실행되고 블록이 어떻게 끝나든 빠져나갈 때 __exit__ 가 실행됩니다. 비동기 컨텍스트 매니저는 같은 개념을 asyncio로 옮긴 것입니다: __aenter____aexit__코루틴이므로, 설정이나 정리가 무언가를 await 할 수 있습니다. 그것들을 구동하는 블록은 async with 입니다.

우리는 이미 하나를 사용했습니다. asyncio.Lock 은 비동기 컨텍스트 매니저입니다. 페이지는 그것을 async with bus_lock: ... 로 사용했습니다. 이 페이지는 애플리케이션 자신의 리소스를 위해 하나를 작성하는 것에 관한 것입니다.

8.12.1. 언제 작성해야 하는가

애플리케이션이 짝을 이루는 설정과 해제가 필요한 리소스를 가지고 있고, 그 양쪽 중 적어도 한쪽이 무언가를 await 해야 할 때입니다. 네트워크 연결, 구성 후 안정화 지연이 필요한 센서, 진입 시 무언가를 잠그고 종료 시 잠금을 해제하는 모든 것입니다. 평범한 동기식 with 형태는 그 __enter____exit__ 가 코루틴일 수 없기 때문에 적용되지 않습니다.

8.12.2. 두 가지 메서드

  • async def __aenter__(self) 는 블록에 진입할 때 실행됩니다. 그것이 반환하는 것이 무엇이든 async with 의 선택적인 as name 절이 바인딩하는 대상이 됩니다. self 를 반환하는 것이 가장 흔한 형태이지만, 어떤 값이든 동작합니다.

  • async def __aexit__(self, exc_type, exc, tb) 는 블록을 빠져나갈 때 실행됩니다. exc_type 은 정상 종료 시 None 이고, 예외(또는 취소) 시에는 예외의 클래스이며 exc 는 그 인스턴스입니다. 참(truthy) 값을 반환하면 Python에게 예외가 처리되었으며 전파되어서는 안 된다고 알립니다. None (보통의 경우)을 반환하면 정리가 실행된 후 예외가 호출 체인을 따라 계속 올라가도록 합니다.

8.12.3. 실제 예제

블록의 본문 동안 LED를 켜는 스포트라이트 래퍼로, 어떤 캡처가 일어나기 전에 조명이 안정되도록 짧은 안정화 지연을 두고, 빠져나갈 때 LED를 다시 끕니다:

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

블록에 진입하면 __aenter__ 가 실행됩니다: LED가 켜지고, 50 ms 안정화 await 는 그동안 다른 코루틴이 진행할 수 있도록 루프에 제어권을 양보하며, 대기가 완료되면 블록 본문이 시작됩니다. 블록이 끝나면 – 정상 종료, 예외, 또는 취소 시 – __aexit__ 가 실행되고 LED가 다시 꺼집니다. 정리는 모든 경우에 실행됩니다. 그것이 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.