본문 바로가기

computer science

코루틴

스스로 메모를 위해서 순서에 대한 맥락이나 두서 없이 코루틴에 대해서 끄젹여 놓은 페이지입니다.
기본 개념을 배우고자 하시는 분은 뒤로 가기를 눌러주세요. :) 

 

 

 

파이썬 공식 문서 : https://docs.python.org/ko/3/library/asyncio.html

 

asyncio — Asynchronous I/O

Hello World!: asyncio is a library to write concurrent code using the async/await syntax. asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance n...

docs.python.org

 

용어 및 개념 정리

 

루틴 : 일련의 명령(코드의 흐름)

 

메인 루틴 : 파이썬에서 "메인 루틴"은 프로그램의 시작점이자 주요 실행 부분을 가리키는 개념입니다. 파이썬 프로그램은 보통 여러 개의 함수와 클래스로 이루어져 있습니다. 이러한 함수와 클래스는 필요한 기능을 구현하고 모듈화하여 코드의 재사용성을 높이는 데에 도움을 줍니다. 그러나 프로그램을 실행하려면 어딘가에서 시작점이 필요합니다. 이 시작점이 바로 메인 루틴(main routine)이라고 부르며, 보통 파이썬 스크립트의 가장 상단에 위치합니다. 메인 루틴은 프로그램이 실행되면 자동으로 실행되며, 프로그램의 주요 작업을 담당합니다.

 

아래에서 main() 함수가 메인 루틴이다. 

def say_hello():
    print("Hello, World!")

def main():
    print("This is the main routine.")
    say_hello()

if __name__ == "__main__":
    main()

 

서브 루틴 : 일반적으로 우리가 알고 있는 함수

 

코루틴 : 서브 루틴의 일반화된 형태. 다양한 진입점과 탈출점이 있는 루틴이다. 

 

 

 

코루틴 사용법

 

일반적인 함수를 코루틴 함수로 변형해보는 예제를 통해 코루틴 사용법을 익혀봅니다.

 

일반적인 동기 함수

def hello_world():
    print("hello world")
    return 123

if __name__ == "__main__":
    hello_world()

 

 

위의 코드를 코루틴으로 변형하기 위해서,

 

(1) async를 함수 앞에 붙여준다. -> await이 없어 Warning 메시지가 뜬다.

async def hello_world():
    print("hello world")
    return 123

if __name__ == "__main__":
    hello_world()

 

 

(2) await을 넣어준다. -> SyntaxError: 'await' outside function이라는 에러가 발생한다. 

async def hello_world():
    print("hello world")
    return 123


if __name__ == "__main__":
    await hello_world()

 

 

(3) asyncio를 import 해주고 asyncio.run()으로 실행한다. -> 해결

import asyncio

async def hello_world():
    print("hello world")
    return 123


if __name__ == "__main__":
    asyncio.run(hello_world())

 

 

 

await은 어디에 붙여야 할까?

 

https://docs.python.org/ko/3/library/asyncio-task.html

 

Coroutines and Tasks

This section outlines high-level asyncio APIs to work with coroutines and Tasks. Coroutines, Awaitables, Creating Tasks, Task Cancellation, Task Groups, Sleeping, Running Tasks Concurrently, Shield...

docs.python.org

 

 

 

태스크(Task) 이해

 

import time
import asyncio


async def delivery(name, mealtime):
    print(f"{name}에게 배달 완료!")
    await asyncio.sleep(mealtime)
    print(f"{name} 식사 완료, {mealtime}시간 소요...")
    print(f"{name} 그릇 수거 완료")

async def main():
    task1 = asyncio.create_task(delivery("A", 2))
    task2 = asyncio.create_task(delivery("B", 3))
	
    await task2
    await task1

if __name__ == "__main__":
    start = time.time()
    asyncio.run(main())
    end = time.time()
    print(end - start)

 

 

 

아래는 aiohttp를 활용한 사례.

 

# pip install aiohttp~=3.7.3

import requests
import time


def fetcher(session, url):
    with session.get(url) as response:
        return response.text


def main():
    urls = ["https://naver.com", "https://google.com", "https://instagram.com"]

    # session = requests.Session()
    # session.get(url)
    # session.close()
    # 위의 close까지 하는 3줄의 코드가 아래 with를 이용하면 2줄로 처리 가능

    with requests.Session() as session:
        result = [fetcher(session, url) for url in urls]
        print(result)


if __name__ == "__main__":
    start_time = time.time()
    main()
    end_time = time.time()
    print("걸린 시간", end_time - start_time)


####################################


import aiohttp
import time
import asyncio


async def fetcher(session, url):
    async with session.get(url) as response:
        return await response.text()


async def main():
    urls = ["https://naver.com", "https://google.com", "https://instagram.com"] * 10

    async with aiohttp.ClientSession(
        connector=aiohttp.TCPConnector(ssl=False)
    ) as session:
        result = await asyncio.gather(*[fetcher(session, url) for url in urls])
        print(result)


if __name__ == "__main__":
    start = time.time()
    asyncio.run(main())
    end = time.time()
    print(end - start)