코루틴이란
- 동시성을 위해 사용자가 쪼갠 하위 구문을 대기시키고, 이어서 실행할는 기능
- 함수 호출의 주/종 관계가 아니므로 시간에 관계 없이 n개의 작업을 대등 관계로 처리할 때 효과적
- 코루틴은 실행 흐름을 저장 및 복원할 수 있어 대기 및 이어서 실행 가능
- 코루틴 스케줄러는 한번에 하나의 코루틴만 이어서 실행하고 나머지는 대기 상태 유지
파이썬 코루틴
- 제너레이터를 개선 사용, 쪼갤 하위 구문 앞에 yield 문 배치
- 제너레이터의 일종이므로 호출 구문은 코루틴을 실행하는 것이 아니라 코루틴 객체만 생성
- 코루틴 객체를 인자로 내장 함수 next()를 호출하면 yield까지 실행한 후 대기
- 인자와 함께 코루틴 객체의 send() 메소드를 호출하면 다음 yield까지 실행
def co_func():
# subroutine - init
print("create")
yield
# subroutine - work
print("start")
yield
co = co_func()
a = next(co) # subroutine - init
co.send(None) # subroutine - work
co.send(None) # stopIteration 예외 발생
- yield를 r-value로 사용하면 send() 메소드로부터 전달받은 인자를 l-value에 대입
- yield 뒤 문장이 있다면 문장까지 실행 후 대기
data = []
def co_func(n):
print("init co_func({0})".format(n))
data1 = yield data.append(n)
# yield 이전까지 실행(오른쪽 명령어)
# 이후 send 메소드에 따라 받은 인자를 data1에 입력
print("call subroutine1({0})".format(data1))
data2 = yield data.append(n+data1)
print("call subroutine2({0})".format(data2))
yield
co = co_func(10)
next(co)
co.send(1)
co.send(2)
코루틴 상태
- 생성, 실행, 대기, 종료 상태
- 코루틴을 호출할 때 생성
- 최초 실행은 next() 함수 호출 통해 수행, 이후 실행은 send() 메소드 호출 통해 수행
- 명시적 종료는 close() 메소드 호출
# gen_created
co = coroutine()
# gen_running ~ "yield"
next(co)
# gen_suspended
# gen_running again
co.send()
# gen_closed
co.close()
# check_stat
from inspect import getgeneratorstate as co_stat
co_stat(co)
데코레이터로 코루틴 추상화
def co_routine(func):
def wrapper(*args, **kwargs):
# coroutine 초기화 구간
co = func(*args, **kwargs)
next(co)
#####
return co
return wrapper
@co_routine
def foo():
while True:
yield
co = foo()
co.send(None)
co.close()
코루틴 결과 반환
@co_routine
def total():
total = 0
while True:
term = yield
if term == None:
break
total += term
return total
# coroutine의 return은 StopIteration 예외 발생
# 반환 대상은 예외 객체의 value 속성에 포함
co = total()
co.send(10)
co.send(20)
try:
co.send(None)
except StopIteration as ret:
print(ret.value)
코루틴과 함수 비교
구분 | 함수 | 코루틴 |
실행 부분 | 문장 모두 실행 | 다음 대기 구문사이만 부분적 실행 |
호출 후 | 호출 후 즉시 실행 | 호출 후 시작 상태만 설정 - next(): 설정 - send(): 실행 |
인자 | 호출 시 인자를 모두 넘김 | 실행 중에도 지속적으로 인자 넘길 수 있음 - send(인자) |
상태 유지 | 속성, 전역 변수, 뮤터블 객체의 매개 변수 초기화 등 필요 - 함수의 상태를 유지하며 전달하려면, 전역 변수 활용 |
지역 변수로 충분 |
코루틴과 제너레이터 비교
구분 | 제너레이터 | 코루틴 |
특징 | 고차원적인 단방향 입력 이터레이터 - 입력으로 사용할 대상을 차례로 반환 |
데이터를 소비하는 이산적 처리에 사용 - 반복되는 시간이 일정치 않은 작업들을 지속적으로 수행 |