본문 바로가기
C.W.K.
Stream
Lesson 01 of 05 · published

asyncio — 기다리는 동안 다른 일을 돌리기

~22 min · asyncio, async, await, coroutine

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

Python의 동시성은 I/O에 강한 asyncio, 막히는 I/O를 함께 처리하는 스레드, CPU 작업을 병렬화하는 프로세스로 나눠 봐. async def 호출은 본문을 실행하지 않고 코루틴을 돌려주며 await해야 진행돼.

asyncio.run은 최상위 이벤트 루프를 열고 닫고, Task는 코루틴을 예약해 함께 진행시켜. Python 3.11의 TaskGroup은 블록을 나가기 전에 만든 작업을 모두 끝내거나 취소하고 여러 실패를 묶어. 만든 작업은 수명과 예외를 회수할 주인이 있어야 해.

Code

가장 작은 비동기 프로그램·python
import asyncio

async def hello():
    print("hi")
    await asyncio.sleep(0.5)              # 'sleep' 이 루프에 제어 양보
    print("world")

# 일반 스크립트에서 — 이벤트 루프 시작
asyncio.run(hello())
# hi
# (반초 일시정지)
# world
순차 실행과 여러 Task 비교·python
import asyncio
import time

async def fetch(name, delay):
    print(f"{name}: 시작")
    await asyncio.sleep(delay)
    print(f"{name}: 완료")
    return name

async def sequential():
    start = time.perf_counter()
    a = await fetch("a", 1)
    b = await fetch("b", 1)
    c = await fetch("c", 1)
    print(f"sequential: {time.perf_counter() - start:.2f}s")

async def concurrent():
    start = time.perf_counter()
    results = await asyncio.gather(
        fetch("a", 1),
        fetch("b", 1),
        fetch("c", 1),
    )
    print(f"concurrent: {time.perf_counter() - start:.2f}s")

asyncio.run(sequential())     # ~3 초
asyncio.run(concurrent())     # ~1 초 — 병렬 실행
Task를 만들고 끝까지 추적하기·python
import asyncio

async def background_work():
    await asyncio.sleep(0.5)
    print("백그라운드 완료")

async def main():
    task = asyncio.create_task(background_work())
    print("task 스케줄")
    # 실행 동안 다른 작업
    await asyncio.sleep(0.1)
    print("메인이 다른 거 함")
    await task                              # 백그라운드 완료까지 기다림
    print("다 됨")

asyncio.run(main())
TaskGroup의 구조적 수명·python
import asyncio

async def fetch(name, delay):
    await asyncio.sleep(delay)
    return f"{name}-result"

async def main():
    async with asyncio.TaskGroup() as tg:
        a = tg.create_task(fetch("a", 0.5))
        b = tg.create_task(fetch("b", 0.3))
        c = tg.create_task(fetch("c", 0.4))
    # 여기서 모든 task 완료, 예외는 ExceptionGroup 로 raise
    print(a.result(), b.result(), c.result())

asyncio.run(main())
# gather + try/except 보다 예외 처리 깔끔
await를 빠뜨렸을 때·python
import asyncio

async def add(a, b):
    return a + b

async def main():
    # 잘못 — await가 없으면 coroutine만 생기고 결과는 없음
    result = add(2, 3)
    print(type(result))                 # <class 'coroutine'>
    print(result)                       # <coroutine object ...>

    # 맞음
    result = await add(2, 3)
    print(result)                       # 5

asyncio.run(main())

# Python 이 종료 시 안 await 된 coroutine 경고

External links

Exercise

지연 뒤 문자열을 돌려주는 fetch 세 개를 gather로 함께 실행해 시간을 재고, 같은 동작을 TaskGroup으로 다시 만들어 결과와 경과 시간을 비교해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.