ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL 2023.04.21
    내일배움캠프 2023. 4. 21. 20:29

    코루틴..

     

    지금까지는 함수를 호출한 뒤 함수가 끝나면 다시 현재 코드로 돌아왔다. 함수 안에서 다른 함수를 호출했을 때 호출한 함수가 끝나면 다시 원래 함수로 돌아온다. 이 때 호출한 함수에 들어있던 변수와 계산식은 모두 사라진다.

    여기서 원래 함수를 메인 루틴(main routine)이라면 함수 안에서 호출 된 함수는 서브 루틴(sub routine)이라고 한다. 

    sub routine = sub + routine  종속적인 루틴을 의미한다.

    메인 루틴에서 서브 루틴을 호출하면 서브 루틴의 코드를 실행한 뒤 다시 메인 루틴으로 돌아온다. 특히 서브 루틴이 끝나면 서브 루틴 안의 내용은 모두 사라진다. 즉 서브 루틴은 메인 루틴의 종속된 관계이다.

     

    코루틴(coroutine)은 조금 다르다. 

    coroutine = cooperative routine을 의미하는데 서로 협력적으로 실행되는 루틴이라는 뜻이다. 메인 루틴과 서브 루틴과의 관계처럼 종속적인 관계가 아니라 서로 대등한 관계 이며 특정 시점에서 상대방의 코드를 실행한다.

     

    코루틴은 제너레이터의 특별한 형태다. 제너레이터는 yield로 값을 발생시켰지만, 코루틴은 yield로 값을 받아올 수도, 반환할 수도 있다. 코루틴에 값을 보내면서 코드를 실행할 때 send 메서드를 사용한다. 

    def my_coroutine():
        while True:                              # 코루틴을 계속 유지하기 위해 무한 루프 사용
            value = yield                        # 코루틴 바깥에서 값을 받아서 value에 저장
            print('Received value:', value)
    
    # 코루틴 객체 생성
    co = my_coroutine()
    
    # 코루틴 실행 준비
    next(co)                                     # 코루틴 yield까지 코드를 실행한다
    
    # 값을 보내기
    co.send('Hello, world!')                     # 코루틴 yield에 값 보내면서 코드를 실행

    코루틴 my_coroutine 은 while True: 로 무한히 반복한다. 왜냐면 코루틴을 종료하지 않고 계속 유지하기 위해서다. value = yield 에서 코루틴 밖에서 받아온 값을 value에 저장하고 print로 출력한다.

    코루틴 밖에선 co = my_coroutine() 으로 코루틴 객체를 생성하고, next(co)로 코루틴을 최초 실행하여 yield 를 만나면 대기한다. co.send로 값을 보내면 코루틴 안에서 값을 받은 뒤 출력한다. 

    >>> Received value: Hello, world!

    my_coroutine 은 무한 루프이기 때문에 다시 yield로 돌와서 대기한다. 다시 send로 값을 보내면 또 출력 하겠지.

     

    코루틴에서 밖으로 값을 전달하려면  yield 변수  와 같이 작성해주면 된다.

    phone_book = {'John': '123-4567', 'Jane': '234-5678', 'Max': '345-6789'}
    
    
    def search():
        name = yield
        while True:
            if name in phone_book:
                phone_number = phone_book[name]
            else:
                phone_number = "cannot find the name in the phone book"
            name = yield phone_number
    
    # 코루틴 객체 생성
    search_coroutine = search()
    next(search_coroutine)
    
    # 검색 개시
    result = search_coroutine.send('John')
    print(result)     # >>> 123-4567
    
    result = search_coroutine.send('Jane')
    print(result)     # >>> 234-5678
    
    result = search_coroutine.send('Sarah')
    print(result)     # >>> cannot find the name in the phone book

    코루틴 search 역시 무한 루프로 코루틴을 계속 유지시킨다. search_coroutine = search() 로 코루틴 객체를 생성해주고, next()로 코루틴을 최초 실행한다. 후 name = yield 에서 멈춘 후 대기한다.

    send 로 값을 보낸다. name 변수에 send로 보내 준 값이 저장되고, 그 값이 phone_book 이라는 딕셔너리에 키로 존재한다면 그 키의 벨류를 phone_number 에 저장 후 yield phone_number 로 코루틴 밖으로 값을 보낸 후 다시 대기한다.

    name = yield phone_number 는 코루틴 바깥에서 값을 받아오면서 바깥으로 값을 전달한다.

     

     

    이런 코루틴을 이용한 비동기 프로그래밍을 위한 라이브러리로 asyncio 가 있다.

    import asyncio
    import random
    
    
    async def fetch_data():
        print("데이터를 가져오는 중...")
        await asyncio.sleep(1) # 데이터를 가져오는데 1초가 걸린다고 가정
        return random.randint(1, 100)
    
    
    async def main():
        data = await fetch_data()
        print(f"가져온 데이터: {data}")
    
    
    asyncio.run(main())

    import asyncio 로 임포트하고

    함수 정의 할 때 앞에 async 를 붙여주면 코루틴 함수를 만들 수 있다.

    await 은 코루틴 안에서 다른 코루틴으의 실행의 완료를 기다린다.

    코루틴을 시작할 땐 run() 메서드를 이용해준다.

    '내일배움캠프' 카테고리의 다른 글

    TIL 2023.04.24  (0) 2023.04.24
    WIL 내일배움캠프 6주차  (0) 2023.04.21
    TIL 2023.04.20  (0) 2023.04.20
    TIL 2023.04.19  (0) 2023.04.19
    TIL 2023.04.18  (0) 2023.04.18
Designed by Tistory.