넘나 쉬운것 ..?
import time
def coroutine_test():
greeting = "good "
while True:
text = (yield greeting)
greeting = "good " # 바뀐 부분
print("text = ",end=""), print(text)
greeting += text
if __name__ == "__main__":
cr = coroutine_test()
print("cr=",end=""), print(cr)
next(cr)
time.sleep(2)
print("send 1")
print(cr.send("morning"))
time.sleep(2)
print("send 2")
print(cr.send("afternoon"))
time.sleep(2)
print("send 3")
print(cr.send("evening"))
time.sleep(2)
결과
cr=<generator object coroutine_test at 0x10e9347b0>
send 1
text = morning
good morning
send 2
text = afternoon
good afternoon
send 3
text = evening
good evening
두번째 코드를 asyncio
와 coroutine
을 활용하여 수정해보기가 두 번째 과제다. 주석에 코드 설명을 놓았다.
import asyncio
"""
코루틴은 반복의 목적이 아니라고 한다.
하지만 나는 반복해서 썼다 .. ㅋㅋ
"""
async def coroutine(num=50000000):
result_value = 0
while result_value < num:
result_value += 1
return result_value
async def main():
"""
코루틴은 "awaitable"한 객체이므로 사용가능하다
await 뒤에 코루틴 객체를 지정하면 해당 객체가 끝날 때까지 기다린 뒤 결과를 반환한다.
async 키워드를 사용하는 네이티브 코루틴만 사용 가능하다.
"""
one = await coroutine()
two = await coroutine()
print("ret_value =",end="")
print(one+two)
print("end of main")
if __name__ == "__main__":
"""
이벤트 루프는 asyncio의 핵심이다.
이벤트 루프는 비동기 태스크 및 콜백을 실행하고
네트워크 IO를 수행하며 자식 프로세스를 실행한다.
"""
loop = asyncio.get_event_loop()
"""
코루틴이 완료할 때 까지 실행한다.
"""
loop.run_until_complete(main())
"""
이벤트 루프를 닫는다.
이 함수를 호출할 때 루프는 반드시 실행 중이지 않아야 한다.
모든 큐를 비우고 실행기를 종료하지만, 완료할 때까지 기다리지 않는다.
"""
loop.close()
실행결과는 다음과 같다.
--- 5.712172031402588 seconds ---
ret_value =100000000
end of main
세번째 과제는 이번 섹션에서 coroutine 을 학습하면서 배운것을 정리해서 블로깅하는 과제이다.
앞서 공부한 프로세스와 스레드는 하나의 변수에 값을 동시에 쓰거나 읽을 때 동기화 문제가 발생해서 여러가지 기법을 동원해서 해결해야 했다. 하지만 코루틴은 이런 기법을 적용하지 않고도 원하는 작업을 할 수 있다.
코루틴 (coroutine)은 cooperative routine을 의미하는데 서로 협력하는 루틴이라는 뜻이다. 즉, 메인 루틴과 서비 루틴처럼 종속된 관계가 아니라 서로 대등한 관계이며 특정 시점에 상대방의 코드를 실행한다. 아래는 파이썬 코딩도장에서 가져온 코루틴의 동작 과정이다.
코루틴은 함수가 종료되지 않은 시점에서 메인 루틴의 코드를 실행하고 다시 돌아와서 코루틴의 코드를 실행할 수 있다.
코루틴의 경우에는 루틴을 진행하는 특정 위치에 멈출 수 있고 필요할 때 다시 나머지 루틴을 수행할 수 있다. 그리고 코루틴은 진입점이 여러개이기 때문에 메인루틴에 종속적이지 않아 대등하게 주고 받을 수 있는 특징이 있다.
파이썬의 코루틴에는 다음과 같은 특징이 있다.
yield
문이라는 특수한 구문이 있다. return
처럼 동작하지만, 사실 입력으로 동작한다.next(coroutine)
은 코루틴 함수의 첫번째 yield
까지 호출하고 대기한다. 다음 next()
를 호출하면 다음 yield
까지 실행한다. 더 이상 yield가 없는데 next를 호출하면 StopIteration
이 발생한다.yield
가 특정 변수에 할당되면, coroutine.send(value)
를 호출해 주어야한다. 즉, yield
를 통해서 메인루틴과 서브루틴간의 값을 이동시키면서 원하는 로직을 수행하면된다.