asyncio gathering multiple results - goddes4/python-study-wiki GitHub Wiki

복수의 task 의 결과를 얻어오는 예제

  • 완료된 순서대로 처리하기
    • process_as_results_come_in()
  • 모든 task가 완료될 때 까지 기다린 후 결과 한번에 받기
    • process_once_everything_ready_with_future()
    • process_once_everything_ready_with_coroutine()
import asyncio
from logging import DEBUG
import random
import threading
import datetime
import logging

MAX_TASKS = 5


@asyncio.coroutine
def long_time_process(task_id):
    """
    예를 들면 외부 open_api 를 이용하여 데이터 수집
    :param task_id:
    :return:
    """
    print(datetime.datetime.now(), threading.current_thread(), "long_time_process start.", task_id)
    wait_time = random.randint(1, 5)
    yield from asyncio.sleep(wait_time)
    return "task {} done. wait time : {}".format(task_id, wait_time)


@asyncio.coroutine
def slow_task(task_id):
    ret = yield from long_time_process(task_id)
    print(datetime.datetime.now(), threading.current_thread(), "slow_task-", task_id, "ret=", ret)
    return ret


@asyncio.coroutine
def process_as_results_come_in():
    coroutines = []
    for i in range(MAX_TASKS):
        coroutines.append(slow_task(task_id=i))

    for coroutine in asyncio.as_completed(coroutines):
        ret = yield from coroutine
        print(ret)


@asyncio.coroutine
def process_once_everything_ready_with_future(event_loop):
    futures = []
    for i in range(MAX_TASKS):
        f = event_loop.create_task(slow_task(task_id=i))
        futures.append(f)

    results = yield from asyncio.gather(*futures)
    print(results)


@asyncio.coroutine
def process_once_everything_ready_with_coroutine(event_loop):
    coroutines = []
    for i in range(MAX_TASKS):
        coroutines.append(slow_task(task_id=i))

    results = yield from asyncio.gather(*coroutines)
    print(results)


logging.basicConfig(level=DEBUG)


def main():
    event_loop = asyncio.get_event_loop()
    event_loop.set_debug(True)

    event_loop.run_until_complete(process_as_results_come_in())
    event_loop.run_until_complete(process_once_everything_ready_with_future(event_loop))
    event_loop.run_until_complete(process_once_everything_ready_with_coroutine(event_loop))
    event_loop.close()
    print("exit")


if __name__ == '__main__':
    main()