콘텐츠로 건너뛰기
Home » asyncio

asyncio

asyncio의 동기화수단들

asyncio는 단일 스레드에서 비동기 코루틴을 사용하여 동시성 처리를 한다. 따라서 asyncio의 세계에서는 적어도 멀티 스레드에서 발생할 수 있는 자원 선점문제가 없을 것이라 생각할 수 있다. 전적으로 틀린 것은 아니다. 스레드가 1개밖에 없기 때문에 메모리 내의 특정한 객체를 동시에 액세스하는 일은 없을 것이다. 그러나 그외의 IO와 관련된 자원은 여전히 선점 문제가 발생할 수 있다. 이러한 문제를 피하기 위해서 asyncio는 threading과 유사한 동기화 수단들을 제공하고 있으며, 이들의 사용 방법 또한 거의 유사하다. asyncio에서 제공하는 동기화 수단에는 다음과 같은 것들이 있다.

  • 락(Lock)
  • 이벤트(Event)
  • 컨디션(Condition)
  • 세마포어(Semaphore)
  • 바운디드세마포어(BoundedSemaphore)
더 보기 »asyncio의 동기화수단들

(Python) Awaitable에 대해

await 키워드를 통해서 실행이 완료되기 전에 다른 작업으로 전환이 가능한 동작을 모두 대기가능(awaitable)하다고 한다. 대기 가능한 객체 타입에는 코루틴(asycio.corutine), Task, Future가 있다.

코루틴

이 글에서 말하는 코루틴은 yield를 사용하는 전통적 의미의 코루틴이 아닌 asycio 라이브러리 내에 정의된 비동기 코루틴을 의미하며, 이는 async def 키워드를 사용하여 정의한 함수(코루틴 함수)가 리턴하는 객체이다. 아래 예제에서 #1의 코드는 실질적으로 아무일도 하지 않는데, nested()를 실행만 하면 코루틴 객체를 생성만 하고 실행(스케줄링)을 하지 않기 때문이다.

더 보기 »(Python) Awaitable에 대해

Asyncio를 사용한 비동기 소켓 통신

이 블로그에서는 파이썬으로 소켓 통신을 구현하는 몇 가지 방법을 이미 살펴본 바 있습니다. 원시 소켓인 socket.socket을 사용하는 방법zmq의 REQ-REP 패턴을 사용한 방법이 있었고, 다중 접속을 허용하도록 스레드를 통해 처리하거나, 셀렉터를 사용하여 단일 스레드에서 멀티플렉싱하는 방법도 알아보았습니다. 이번 글에서는 asyncio에서는 과연 소켓 통신을 어떤식으로 구현하는지 살펴보고 역시나 간단한 비동기 다중 접속 에코 서버를 구현하는 과정을 함께 살펴보겠습니다.

더 보기 »Asyncio를 사용한 비동기 소켓 통신

ZMQ + Asyncio 적용하기

파이썬에서 ZMQ를 사용할 때, asyncio를 사용할 수 있게 되었다. asyncio에 적용한다고 해서 크게 달라지는 것은 없고 소켓의 사용방법은 대동소이하다. (실제 IO 시점에 작업 전환이 일어날 수 있게 await를 붙이는 것 정도의 차이만 있다. 대략의 사용법을 정리해보면 다음과 같다.

더 보기 »ZMQ + Asyncio 적용하기

ZMQ 예제 – Poller를 사용하여 종료 시점을 동기화하기

하나의 ZMQ 소켓은 여러 포트에 바인드하거나 커넥트할 수 있어서, 1:N의 연결을 쉽게 구성할 수 있습니다. 하지만 어떤 경우에는 이 다중 접속이 두 개 이상의 소켓을 사용하는 경우도 있습니다. 이런 경우 두 개의 소켓을 동시에 듣는 방법이 필요합니다. ZMQ소켓의 recv() 메소드는 블럭킹 함수이기 때문에 2개 이상의 소켓 중 데이터가 들어온 소켓을 처리하기 위해서는 소켓만으로는 처리할 수 없습니다. ZMQ는 이런 상황에 사용할 수 있는 Poller라는 수단을 제공합니다.

더 보기 »ZMQ 예제 – Poller를 사용하여 종료 시점을 동기화하기

Asyncio – 네트워크 입출력을 위한 스트림

asyncio는 네트워크 입출력을 위한 스트림이라는 타입을 제공하고 있다. 스트림은 네트워크 연결을 만들거나(클라이언트의 connect 동작) 서버를 시작하고(서버의 bind/listen 동작) 연결이 생성되면 해당 연결을 처리하는 핸들러의 인자로 넘겨지게 된다. 비동기 코루틴인 각각의 핸들러는 이 스트림을 이용해서 데이터를 읽거나 전송할 수 있다.

입출력 스트림은 내부적으로 소켓을 감싸고 있으며, 노출되는 API를 통해서 소켓을 기다리고 읽고 쓰는 일련의 작업을 상당히 고수준의 레벨에서 제공해주고 있다.

더 보기 »Asyncio – 네트워크 입출력을 위한 스트림

async with : 비동기 컨텍스트 매니저

파이썬의 컨텍스트 매니저with 블럭을 적용할 수 있는 객체를 말한다. 이러한 객체들은 with 절에서 마치 블럭에 대한 데코레이터처럼 동작한다. 가장 흔한 예가 open() 함수로 생성하는 파일 입출력스트림으로, with 구문 내에서 쓰이면 블럭을 빠져나갈 때 파일을 닫는 동작을 자동으로 수행하게 된다.

with open('data.txt') as f:
  for line in f:
    print(line)

컨텍스트 매니저 객체는 __enter__(), __exit__() 두 개의 내장 메소드를 가지고 있는 것으로 간주된다. 위 코드에서는 with 다음에 나오는 open('data.txt') 라는 코드는 파일에 대한 입출력 스트림을 반환한다. 그리고 with 문을 빠져나갈 때, 파일에 대해 __exit__()가 호출되고 여기서 파일이 닫힐 것이다.

더 보기 »async with : 비동기 컨텍스트 매니저

asyncio – 일반 함수를 비동기로 사용하기

지난 글에서 urlopen()과 같은 표준 라이브러리 함수를 어떻게 비동기 코루틴처럼 asyncio에서 사용할 수 있는지 살펴보았다. aiohttp 등의 비동기 라이브러리를 사용해서 여러 핸들러를 작성해야 할 때, 이와 같은 처리를 많이 해야 한다면 빈번하게 런루프 메소드를 호출하는 것보다, 간단히 데코레이터를 만들어서 활용하는 것이 어떨까? asyncio의 이벤트 루프에는 run_in_executor(executor, fn, *args) 가 있다. 이 메소드는 concurrent.futures 모듈의 ThreadPoolExecutor나 ProcessPoolExecutor를 사용하여 일반적인 blocking 함수를 다른 스레드 및 프로세스에서 실행하도록 하고 그 자신은 처리를 기다리는 코루틴을 생성한다. 이 기능을 사용하면 일반적인 blocking-I/O 함수를 non-blocking 함수처럼… 더 보기 »asyncio – 일반 함수를 비동기로 사용하기