티스토리 뷰

python lecture/basic

[edu[ coroutine (코루틴)

burningrizen 2019. 1. 30. 15:28

파이썬에서 스레드를 사용하여 여러 기능을 동시에 실행하는 것처럼 보여줄 수 있습니다. 


하지만 스레드를 사용하는 데는 크게 3가지 문제가 있습니다.


1. 스레드들이 서로 안전하게 동작하도록 조율하려면 특별한 도구가 필요합니다. 따라서 스레드를 사용하는 코드가 절차적인 싱글 스레드 보드보다 이해하기 어렵습니다. 또한 이런 복잡성 때문에 시잔이 지날수록 스레드 코드를 확장하거나 유지보수 하기 어렵습니다.


2. 스레드에는 메모리가 많이 필요합니다.(스레드당 약 8MB정도). 많은 컴퓨터에서 스레드를 수십 개 가량 실행할 때는 문제가 되지 않습니다. 하지만 프로그램이 함수 수천 개를 동시에 실행한다면 문제가 발생합니다. 이러한 함수는 사용자가 서버에 보내는 요청, 화면의 픽셀, 시뮬레이션의 입자에 대응할지도 모릅니다. 고유의 활동마다 스레드를 하나씩 실행한다면 당연히 제대로 동작하지 않을 것입니다.


3. 스레드를 시작하는 데는 비용이 많이 듭니다. 끊임없이 새 병행 함수를 생성하고 종료하면 스레드를 사용하면서 드는 부하가 커저 전체 시스템이 느려집니다.



파이썬에서는 코루틴(coroutine)으로 이런 문제를 모두 해결할 수 있습니다. 


코루틴을 사용하면 파이썬 프로그램에서 동시에 많은 함수를 실행하는 것처럼 보이게 할 수 있습니다.


코루틴은 제네레이터를 확장하는 방법으로 구현합니다.


제네레이터 코루틴을 시작하는데 드는 비용은 함수 호출입니다.


따라서 한 번 활성화되면 소진시 까지 1KB 미만의 메모리만 소비합니다.







def printer():
while True:
line = yield
print("message: {}".format(line))


def grep():
p = printer()
p.__next__()
while True:
line = input()
if line:
    yield p.send(line)


g = grep()
while True:
g.__next__()


generator 는 소비하는 입장이라면 coroutine 은 생산하는 입장이다.


printer() 는 코루틴인데 yield 통해 외부에서 데이터를 입력 받을 수 있다.


그리고 그다음 입력을 받기 전까지 대기 상태다.


send 를 통해서 입력 받는다.



코루틴을 시작하기 위해서는 next() 를 실행해야 한다. 


매번 해주기 귀찬으니 코루틴 decorator 를 만들어서 사용하자


from functools import wraps


def coroutine(func):
@wraps(func)
def wrapper(*args, **kwargs):
cr = func(*args, **kwargs)
cr.__next__()
return cr
return wrapper


@coroutine
def printer():
while True:
line = yield
print("message: {}".format(line))


def grep():
p = printer()
while True:
line = input()
if line:
yield p.send(line)


g = grep()
while True:
g.__next__()





댓글