Python

[Python] 비동기 - asyncio.create_task

비번변경 2024. 12. 6. 10:34

개요

2024.06.26-[Python] asyncio - 비동기 프로그래밍에서 asyncio.run, 그리고 await을 이용한 코루틴 실행 방법을 알아보았다. 사실 코루틴 실행 방법은 한 가지 더 존재하는데, 바로 create_task 함수를 이용하는 방법이다.

이번 글에서는 create_task를 이용한 비동기 프로그래밍을 정리한다.

 

 

create_task

asyncio.create_task(coro, *, name=None, context=None)

전달받은 코루틴으로 Task 객체를 생성하고 실행을 예약한다. Task 객체를 반환한다.

Task는 get_running_loop으로 반환된 이벤트루프에서 실행되고, 현재 스레드에 실행 중인 이벤트 루프가 없으면 RuntimeError가 발생한다.

보통 여러 개의 코루틴을 동시에 실행시키고 싶을 때 사용하는 것 같다.

 

예시 )

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)
    
async def main():
    task1 = asyncio.create_task(say_after(1, 'hello'))
    task2 = asyncio.create_task(say_after(2, 'world'))
    print(f"started at {time.strftime('%X')}")

    # Wait until both tasks are completed (should take around 2 seconds.)
    await task1
    await task2
    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

 

 

create_task vs await

create_task, await 모두 코루틴을 실행시키지만 두 방법에는 약간의 차이가 있다.

create_task는 create_task 시점에 바로 코루틴의 실행을 예약한다. 따라서 위의 예시 코드는 다음과 같이 동작한다

  1. asyncio.run(main()) : 비동기 진입
  2. task1 : say_after(1, 'hello') 생성 및 실행 예약
  3. task2 : say_after(2, 'world') 생성 및 실행 예약
  4. await task1, await task 2 : 실행 대기

코루틴의 실행은 create_task에 이미 진행되고 있고, await는 단지 완료를 대기한다.

 

반면 await의 경우 코루틴을 실행시킨 후 반환을 기다린다. 아래 코드는 say_after를 await으로 호출하도록 변경한 것이다. 

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

이때의 동작은 다음과 같다.

  1. asyncio.run(main()) : 비동기 진입
  2. await say_after(1, 'hello') : 코루틴 실행 및 대기
  3. await say_after(2, 'world') : 코루틴 실행 및 대기

task를 생성하고 실행을 바로 예약하는 create_task와 다르게 await는 코루틴을 실행하고 완료를 대기한다. 결과적으로 두 개의 작업에 2초가 소요되는 create_task와 달리 await는 3초가 소요된다.

 

달리 말하면, 아래의 두 메인 함수는 본질적으로 동일하다.

async def main():
    await say_after(1, 'hello')
    
    
async def main():
    task1 = asyncio.create_task(say_after(1, 'hello'))
    await task1

 

 

참고 문서

https://teddylee777.github.io/python/python-async/

https://kdw9502.tistory.com/6

https://forum.micropython.org/viewtopic.php?t=9384