티스토리 뷰

Programming/Language

Async IO in Python <1>

prograsshopper_ 2022. 9. 20. 21:45

* real python의 글을 거의 그대로 번역한 글로, 엉터리 번역이 있을수있어 원문을 읽는걸 권장 (일단 일부밖에 안했다는 점이..)

- https://realpython.com/async-io-python/
- 참고: https://realpython.com/courses/python-3-concurrency-asyncio-module/

 

Hands-On Python 3 Concurrency With the asyncio Module – Real Python

Learn how to speed up your Python 3 programs using concurrency and the asyncio module in the standard library. See step-by-step how to leverage concurrency and parallelism in your own programs, all the way to building a complete HTTP downloader example app

realpython.com

The 10,000-Foot View of Async IO

병렬성

  • 다양한 동작들을 동시에 하는 것으로 간주된다. 멀티프로세싱이 병렬성을 수행하기 위한 수단이며, CPU등을 사용해 작업을 분산한다. 멀티 프로세싱은 CPU 바운드 작업에 적합하다; for 루프와 수학적 연산

동시성

  • 병렬성보다 더 넓은 개념으로 여러 작업이 겹치는 방식으로 실행될 수 있음을 나타낸다. (동시성은 병렬성과 같은 의미가 아니라고도 한다)

스레딩

  • 동시성을 수행하는 모델로 IO바운드 작업에 적합하다. CPU 바운드 작업은 처음부터 끝까지 지속적으로 열심히 작동하는 컴퓨터 코어가 특징인 반면, IO 바운드 작업은 입력/출력이 완료될 때까지 많은 대기 시간이 대부분이다.

요약하면 동시성은 멀티프로세싱과 스레딩 둘 다를 포함한다. 멀티 프로세싱은 벙렬성의 형태이며, 병렬성은 동시성의 하위 개념이다. 위의 세 개념을 지원하는 파이썬 표준 라이브러리로 multiprocessing, threading, concurrent.futures 패키지가 있다.


asynchronous IO

  • 표준 라이브러리: asyncio 패키지
  • async io는 동시성 프로그래밍의 형식이지만 병렬성은 아니다. 멀티프로세싱보단 스레딩과 가까우나 결국 스레딩도 아니며 동시성 트릭중 하나인 독립 실행형 멤버다.
  • 비동기(Asynchronous)란 무엇인가?
    • 비동기 루틴은 결과를 기다리는 동안 "일시 중지"하고 그 동안 다른 루틴이 실행되도록 할 수 있다. 비동기 코드(Asynchronous Code)는 위의 메커니즘을 사용해서 동시 실행을 촉진할 수 있는데 정확히는 보기에 그렇다는 것이다.
    • 비동기식 IO는 오랜 대기 시간을 필요로 하는 기능은 블로킹하고, 그동안 다른 기능이 실행될 수 있도록 한다.
    • 가능하면 스레딩보다는 Async IO를 사용하는 것을 권장하는데 Async IO는 스레드 디자인에서 오는 잠재적인 속도 저하를 피할 수 있기 때문이다.


asyncio Package & keyword: async/await

Coroutine

- async IO의 핵심. 파이썬 제너레이터 함수의 특수한 버전이라고 할 수 있다.

- 리턴에 이르기 전에 실행을 일시적으로 중단할 수 있는 함수로, 일정 시간동안 간접적으로 다른 코루틴에 제어를 넘길 수 있다.

예제

  • 각 작업이 await asyncio.sleep(1)에 이르면 이 함수는 이벤트루트에 1초동안 sleep할테니 그동안 다른 작업을 하라고 알려주고 제어를 넘겨준다.
import asyncio

async def count():
    print("One")
    await asyncio.sleep(1)
    print("Two")

async def main():
    await asyncio.gather(count(), count(), count())

if __name__ == "__main__":
    import time
    s = time.perf_counter()
    asyncio.run(main())
    elapsed = time.perf_counter() - s
    print(f"{__file__} executed in {elapsed:0.2f} seconds.")
$ python3 countasync.py
One
One
One
Two
Two
Two
countasync.py executed in 1.01 seconds.

 

* time.sleep() 과 asyncio.sleep()을 쓰는 예제가 다소 진부해보일수는 있으나, 여기서 time.sleep()은 시간이 오래 걸리는 블로킹 함수 호출을 상징하고 asyncio.sleep()은 논블로킹 함수를 상징한다고 생각하면 될 것이다.

asyncIO의 법칙

  • async def: 비동기제너레이터 혹은 네이티브 코루틴을 소개하는 용어다.
  • await: 함수 제어를 이벤트루프로 넘기는 것을 의미한다. 이것은 감싸고있는 코루틴의 수행을 멈출 수 있다.
  • await 또는 return을 사용하면 코루틴 함수가 생성된다. 코루틴 함수를 호출하려면 결과를 얻을 때까지 기다려야 한다.
  • yield를 async def 블록에서 사용하는건 흔치 않은 방식이다. (오직 최신 파이썬에선 유효하다)
  • async def로 정의된 것은 yield를 사용하지 않도록 권장되고 사용시 syntaxError를 일으킨다.
  • await f()를 사용할때 f()는 awaitable한 객체여야만 한다. 이런 객체의 종류에는 (1)다른 코루틴이거나 (2) .__await__() 메서드가 정의되어있고 이터레이터를 리턴하는 객체여야만 한다.

코루틴을 사용할땐 암시적인 패턴이 아니라 명시적인 패턴을 사용하도록 한다. 암시적-Generator-based coroutines는 파이썬 3.10에서 없어질 예정이다.

반응형

'Programming > Language' 카테고리의 다른 글

Python의 가비지 콜렉터와 메모리 관리  (0) 2022.08.15
Typescript 시작!  (0) 2021.05.15
댓글