이번 포스팅은 coroutine입니다. 지금까지는 주로 한번 실행되고 종료되는 함수들이었는데요! coroutine
은 여러번 호출될 수 있고, 호출되면서 상태를 유지할 수도 있습니다.
generator
에서 yield 구문을 이용해 값을 여러번 반환할 때 yield 호출 후에 다시 next가 호출될 때까지 현재의 상태에서 머물고 있다가 next가 호출될 때 yield로 값을 산출하였습니다.
generator과 coroutine 모두 yield 키워드를 필수적으로 가지고 있습니다. generator는 yield로 값을 산출한 반면 coroutine은 값을 받아온다는 차이점이 있습니다.
다음은 스레드, 프로세서에서 다루었던 1억을 증가시키는 코드의 코루틴 버전입니다.
def coroutine_1():
return_value = 0
while True:
input_value = (yield return_value)
return_value = input_value + 1
def coroutine_2():
return_value = 0
while True:
input_value = (yield return_value)
return_value = input_value + 1
if __name__ == "__main__":
ret_value = 0
c1 = coroutine_1()
c2 = coroutine_2()
next(c1)
next(c2)
while ret_value < 100000000:
ret_value = c1.send(ret_value)
ret_value = c2.send(ret_value)
print("ret_value =",end=""), print(ret_value)
print("end of main")
코루틴은 send()
메서드를 호출하기 전에는 수행되지 않고 while문의 yield에서 대기합니다. 원하는 시점에 send()
메서드를 호출해서 코루틴과 협력해 프로그램을 만들 수 있고, c1과 c2의 코루틴에 보내는 중간에 원하는 작업을 할 수 있습니다.
코루틴은 앞서 살펴보았던 멀티태스킹 기능과 비교해서 동기화 문제에서 자유롭다는 장점이 있습니다.
Asynchronous I/O
는 코루틴과 관련된 async/await
구문을 활용해 동시성 코드를 작성하는 라이브러리입니다. 이는 파이썬의 비동기처리 프레임워크의 기반으로 활용되며, CPU작업과 I/O를 병렬로 처리하기 합니다. 코루틴은 파이썬 3.10버전에서 삭제될 예정으로 파이썬에서 코루틴을 활용하기 위해선 asyncio
을 활용합니다.
import asyncio
import time
async def coroutine_1(): #async문으로 coroutine_1 정의
return_value = 0
while return_value<50000000:
# input_value = (yield return_value)
return_value += 1
return return_value
async def coroutine_2(): #async문으로 coroutine_2 정의
return_value = 0
while return_value<50000000:
# input_value = (yield return_value)
return_value +=1
return return_value
async def main(): #최상위 진입점 main() 정의
c1 = await coroutine_1()
c2 = await coroutine_2()
print("ret_value =",end=""), print(c1+c2)
print("end of main")
if __name__ == "__main__":
start_time = time.time()
asyncio.run(main())
print(f"--- {time.time() - start_time} seconds ---") # 처리 시간 계산