[Python] Asyncio_05

atesi·2022년 9월 22일
0

asyncio

목록 보기
5/7

Asynchronous Context Managers

비동기식 컨텍스트 매니저는 상당히 논리적으로 비동기식 환경에서 작동하는 컨텍스트 매니저 개념의 확장이며 비동기식 기반 라이브러리 인터페이스에서 많이 사용된다.

비동기 컨텍스트 매니저는 async with문에서 사용할 수 있는 객체이다. 이에 대한 예는 다음과 같다.

async with FlowProvider(store_url) as provider:
    async with provider.open_read(flow_id, config=config) as reader:
        frames = await reader.read(720, count=480)

        # Do other things using reader
        ...

    # Do other things using provider
    ...

# Do something with frames
...

위의 예에서 FlowProvider 메소드는 비동기 컨텍스트 매니저를 반환하며 provider.open_read도 그러하다.

  • FlowProvider에 대해 일부 리소스를 가져오거나 설정하고 그 결과는 provider에게 바인딩 된다.
  • procider.open_read에 대해 추가 리소스를 가져오거나 설정을 수행하고 그 결과는 reader에게 바인딩 된다.
  • 비동기 컨텍스트 매니저 내부에 코드블럭이 있고, 그 안의 reader 객체를 사용할 수 있으므로 프레임 목록을 반환하는 코루틴 reader.read를 await할 수 있다.
  • reader를 사용하는 다른 작업이 수행된다.
  • async with 문의 코드 블록이 일부 구성을 완료했으므로 reader에 대한 리소스 할당이 취소된다.
  • provider를 사용하는 다른 작업이 수행된다.
  • async with 문의 코드 블록이 일부 구성을 완료했으므로 provider에 대한 리소스 할당이 취소된다.
  • 비동기 컨텍스트 매니저 외부에서 reader, provider 정리가 완료되었지만 frames와 같은 변수는 여전히 액세스할 수 있고 values를 보유한다.

이것은 본질적으로 with 문을 사용하는 일반 동기 컨텍스트 매니저의 사용 및 프로세스와 동일하다.

차이점은 시작(entry)과 종료(exit) 시 수행되는 설정(setup) 및 해제(teardown)는 비동기 코루틴을 기다리면서 수행된다는 점이다.

이는 컨텍스트의 시작 및 종료를 위해 비동기식 컨텍스트 매니저에서 제공되는 코드가 비동기식 코드일 수 있고(즉 await, 명령문을 포함할 수 있음) 또한 async with 비동기식 코드가 허용되는 컨텍스트에서만 사용할 수 있음을 의미한다.(예: 코루틴 함수의 코드 블록 내부).

그러나 메소드 FlowProviderprovider.open_read는 코루틴 메소드가 아니며 비동기 컨텍스트 매니저 객체를 반환하는 일반적인 메서드이다. 이는 일반적이며 비동기 코루틴을 반환하는 코루틴을 보는 것은 매우 드물다.

사실 async with문은 await문을 포함한 더 복잡한 코드블럭을 작성하기 위한 줄임말이다.

async with AsyncCM as ctx:
    ...

# Is the same as:

ctx = await AsyncCM.__aenter__()
try:
    ...
except Exception as e:
    if not await AsyncCM.__aexit__(type(e), e, e.__traceback__):
        raise e
else:
    await AsyncCM.__aexit__(None, None, None)

매직 코루틴 매소드를 수행하는 클래스를 만들어 자신만의 비동기 컨택스트 매니저를 쉽게 정의 가능하다.

async def __aenter__(self):
    ...

async def __aexit__(self, exc_t, exc_v, exc_tb):
    ...

__aexit__를 취하는 파라미터와 이러한 코루틴의 반환 값들은 다음과 같이 정의된다.

  • __aenter__의 반환 값은 무엇이든 될 수 있다. 반환 값이 무엇이든async with문에서 as절에 의해 바인딩 될 객체이다.
  • async with문의 코드블럭이 예외 없이 끝에 도달하면 __aexit__는 세 개의 매개변수를 모두 None으로 사용하여 호출되며 반환 값은 무시된다.
  • async with문의 코드블럭이 예외를 발생하면 __aexit__는 세 개의 매개변수를 예외의 타입, 예외 객체 그 자체, 그리고 "traceback"으로 호출한다. 만약 Ture를 반환한다면 (또는 사실로로 평가되는 것) 시스템은 예외가 처리 및 수정된 것으로 가정하고 더 이상 propagate(전파)하지 않는다. False, None, 거짓으로 평가되는것, 아무것도 반환되지 않으면 예외가 계속 전파된다.

이 동작은 동기 컨택스트 매니저를 정의할 때 사용되는 매직메소드 __enter__, __exit__와 깔끔하게 미러링한다.

profile
Action!

0개의 댓글