1.코루틴
- 함수는 메인 루틴에서 서브 루틴을 호출하면 서브 루틴의 코드를 실행 한 뒤 다시 메인 루틴으로 돌아옴
서브 루틴이 끝나면 서브 루틴의 내용이 모두 사라짐
서브 루틴은 메인 루틴에 종속된 관계
- 코루틴은 두 루틴이 대등한 관계인 상태에서 특정 시점에 상대방의 코드를 실행하는 방식
- 코루틴은 코드를 여러 번 실행할 수 있음
- 함수가 종료되지 않은 상태에서 메인 루틴의 코드를 실행 한 뒤
- 다시 돌아와서 코루틴의 코드를 실행
- 코루틴이 종료되지 않았으므로 코루틴의 내용도 계속 유지
def 코루틴이름():
while True:
변수 = (yield) # 코루틴 바깥에서 값을 받아옴
코루틴객체 = 코루틴()
next(코루틴객체) # 코루틴 안의 yield까지 코드 실행(최초 실행), __next__메소드도 같음
코루틴객체.send(값) # 코루틴에 값을 보냄
def 코루틴이름():
while True:
변수 = (yield 변수) # 코루틴 바깥에서 값을 받아오면서 바깥으로 값을 전달
코루틴객체 = 코루틴()
변수 = next(코루틴객체) # 코루틴 안의 yield까지 코드를 실행하고 코루틴에서 나온 값 반환
변수 = 코루틴객체.send(값) # 코루틴에 값을 보내고 코루틴에서 나온 값 반환
1-2.코루틴에 값 보내기
- 코루틴은 제너레이터의 특별한 형태
yield로 값을 발생시켰지만 코루틴은 yield로 값을 받아올 수 있음
send 메소드가 보낸 값을 받아오려면 (yield) 형식으로 변수에 저장
코루틴객체.send(값)
변수 = (yield)
next(코루틴객체)
def number_coroutine():
while Ture: # 코루틴을 계속 유지하기 위해 무한 루프 사용
x = (yield) # 코루틴 바깥에서 값을 받아옴
print(x)
co = number_coroutine()
next(co) # 코루틴 안의 yield까지 코드 실행(최초 실행)
co.send(1) # 코루틴에 숫자 1을 보냄
co.send(2) # 코루틴에 수자 2를 보냄
co.send(3) # 코루틴에 숫자 3을 보냄
- 코루틴은
yield에서 함수 중간에 대기한 다음 메인 루틴을 실행하다가 다시 코루틴을 실행함
2.코루틴 바깥으로 값 전달하기
(yield 변수) 형식으로 yield에 변수를 지정한 뒤 괄호로 묶어주면 값을 받아오면서
값을 바깥으로 전달
next는 코루틴의 코드를 실행하지만 값을 보내지 않을 때 사용
send는 값을 보내면서 코루틴의코드를 실행할 때 사용
변수 = (yield 변수)
변수 = next(코루틴객체)
변수 = 코루틴객체.send(값)
def sum_coroutine():
total = 0
while True:
x = (yield total) # 코루틴 바깥에서 갑을 받아오면서 바깥으로 값을 전달
total += x
co = sum_coroutine()
print(next(co)) # 0: 코루틴 안의 yield까지 코드를 실행하고 코루틴에서 나온 값 출력
print(co.send(1)) # 1: 코루틴에 숫자 1을 보내고 코루틴에서 나온 값 출력
print(co.send(2)) # 3: 코루틴에 숫자 2를 보내고 코루틴에서 나온 값 출력
print(co.send(3)) # 6: 코루틴에 숫자 3을 보내고 코루틴에서 나온 값 출력
- 코루틴에서 값을 누적할 변수 total을 만들고 0 할당
- x = (yield total)과 같이 값을 받아오면서 바깥으로 값을 전달
- 바깥에서 send가 보낸 값은 n에 저장
- 코루틴 바깥으로 보낼 값은 total
2-1.제너레이터 vs 코루틴
- 제너레이터 : next 함수
__next__메소드를 반복 호출하여 값을 얻어내는 방식
- 코루틴 : next 함수
__next__메소드를 한번 호출한 뒤 send로 값을 주고받는 방식
3.코루틴을 종료하고 예외 처리하기
- 코루틴은 실행 상태를 유지하기 위해
while True:를 사용해서 무한 루프로 동작
- 코루틴을 강제로 종료하고 싶다면
close 메소드를 사용
- 코루틴 객체에서
close 메소드를 사용하면 코루틴 종료
def 코루틴이름():
try:
실행할 코드
except GeneratorExit: # 코루틴이 종료될 때 GeneratorExit 예외 발생
예외가 발생했을 때 처리하는 코드
코루틴객체 = 코루틴()
next(코루틴객체)
코루틴객체.close() # 코루틴 종료
def 코루틴이름():
try:
실행할 코드
except 예외이름 as e: # e에는 throw 메소드에 지정한 에러 메시지에 들어감
yield 값 # except에서 yield에 지정한 값은 throw 메소드의 반환값으로 나옴
코루틴객체 = 코루틴()
next(코루틴객체)
코루틴객체.throw(예외이름, 에러메시지) # 코루틴 안에 예외를 발생시킴
def number_coroutine():
while True:
x = (yield)
print(x, end=' ')
co = number_coroutine()
next(co)
for i in range(20):
co.send(i)
co.close() # 코루틴 종료
3-1.GeneratorExit 예외 처리하기
- 코루틴 객체에서
close 메소드 호출하면 코루틴이 종료될 때 GeneratorExit 예외가 발생
- GeneratorExit 예외를 처리하면 코루틴의 종료 시점을 알 수 있음
def number_coroutine():
try:
while True:
x = (yield)
print(x, end=' ')
except GeneratorExit: # 코루틴이 종료될 때 GeneratorExit 예외 발생
print()
print('코루틴 종료')
co = number_coroutine()
next(co)
for i in range(20):
co.send(i)
co.close()
3-2.코루틴 안에 예외 발생시키기
- 코루틴 안에 예외를 발생시킬 때는
throw 메소드를 사용
throw 메소드에 지정한 에러 메시지는 except as의 변수에 들어감
코루틴객체.throw(예외이름, 에러메시지)
def sum_coroutine():
try:
total 0
while True:
x = (yield)
total += x
except RuntimeError as e:
print(e)
yield total # 코루틴 바깥으로 값 전달
co = sum_coroutine()
next(co)
for i in range(20):
co.send(i)
print(co.throw(RuntimeError, '예외로 코루틴 끝내기')) # 190. 코루틴의 except에서 yield로 전달받은 값
4.하위 코루틴의 반환값 가져오기
yield from에 코루틴을 지정하면 해당 코루틴에서 return으로 반환값 가져옴
변수 = yield from 코루틴()
def 코루틴A():
변수 = (yield) # 코루틴 바깥에서 값을 받아옴
return 값 # return으로 값을 반환, raise StopIteration(값)과 동작이 같음
def 코루틴B():
변수 = yield from 코루틴A() # 코루틴A의 반환값을 가져옴
def accmulate():
total = 0
while True:
x = (yield) # 코루틴 바깥에서 값을 받아옴
if x in None: # 받아온 값이 None이면
return total # 합계 total을 반환
total += x
def sum_coroutine():
while True:
total = yield from accumulate() # accumulate의 반환값을 가져옴
print(total)
co = sum_coroutime()
next(co)
for i in range(1, 11): # 1부터 10까지 반복
co.send(i) # 코루틴 accumulate에 숫자를 보냄
co.send(None) # 코루틴 accumulate에 None을 보내서 숫자 누적을 끝냄
for i in range(1, 101): # 1부터 100까지 반복
co.send(i) # 코루틴 accumulate에 숫자를 보냄
co.send(None) # 코루틴 accumulate에 None을 보내서 숫자 누적을 끝냄
4-1.Stoplteration 예외 발생시키기
- 코루틴도 제너레이터이므로 return을 사용하면 Stoplteration이 발생
- raise로 예외를 직접 발생시키고 값을 지정하면
yield from으로 값을 가져올 수 있음
raise Stoplteration(값)
def accmulate():
total = 0
while True:
x = (yield) # 코루틴 바깥에서 값을 받아옴
if x in None: # 받아온 값이 None이면
raise Stoplteration(total) # Stoplteration에 반환할 값을 지정
total += x
def sum_coroutine():
while True:
total = yield from accumulate() # accumulate의 반환값을 가져옴
print(total)
co = sum_coroutime()
next(co)
for i in range(1, 11): # 1부터 10까지 반복
co.send(i) # 코루틴 accumulate에 숫자를 보냄
co.send(None) # 코루틴 accumulate에 None을 보내서 숫자 누적을 끝냄
for i in range(1, 101): # 1부터 100까지 반복
co.send(i) # 코루틴 accumulate에 숫자를 보냄
co.send(None) # 코루틴 accumulate에 None을 보내서 숫자 누적을 끝냄