엄범

 

coroutine

코루틴이란 ? 각 루틴이 종속적인 관계 아닌(caller, callee 관계인 subroutine이 아닌) 대등한 관계로, 서로를 순차적으로 호출하도록 되어 있는 함수

 

~3.4 에서는 제너레이터를 사용해 코루틴을 구현

제너레이터는 어디까지 실행했는지를 기억했다가 나중에 다시 그 부분부터 실행되기 때문에, 이를 Future와 결합하면 코루틴을 구현하기 용이

```python

# next(c) 한 번 호출 시 다음 yield까지 실행.

# 즉 아래 함수는 next(c)를 3번 호출 가능

def coro():

    # 밑줄 부분을 실행("yield1" 반환)하고 첫 번째 멈춤. 즉 hello = ???는 아직 실행 전.

    hello = yield "yield1"   
    yield hello    # hello를 반환하고 두 번째 멈춤

    print("end")

    # 세 번째 next에서 종료되며 StopIteration

    
c = coro()
print(next(c))          # 첫 번째 yield까지 실행. yield1을 반환

 

# send()로 yield 표현식에 값을 전달할 수 있다.

print(c.send("World"))  # hello = {"World"} & yield hello를 실행. 

 

next(c)    # end 출력하고 종료되면서 StopIteration

```

  • 이렇게 코루틴은 yield를 만나면 제어권을 넘기면서 실행한다.
  • 지금은 Coroutine을 직접 main에서 불러주었지만, 코루틴들을 EventLoop 위에서 실행하도록 할 수 있다. (`` asyncio``에서는 이를 API로 지원한다.)
    • 간단한 EventLoop는 아래와 같은 형식이 된다.

```python

class EventLoop(Queue):

    def start(self):

        while True:

            coro = self.get()

            coro()

```

 

3.4    generator based coroutine

```python

import asyncio

 

@asyncio.coroutine

def cortn():

    yield from asyncio.sleep(1.0)

    print('Hello, world!')

 

loop = asyncio.get_event_loop()

loop.run_until_complete(cortn())

loop.close()

```

Note ) ``python await == yield from`` 이다.

 

asyncio    ( HTTP : aiohttp )

  • 단일 thread에서 코드가 진행되므로 CPU에서 context switching이 일어나지 않기 때문에 CPU 코어 수준의 병렬 처리는 일어나지 않는다. (단일 코어에서의 context switching을 말한다. [GIL])
    그러나 각 코드는 이벤트 루프 위에서 제어권을 주고 받으며 돌아가기 때문에 동시에 실행되는 것 처럼 보인다.
  • ``python await``를 만나면 해당 코루틴의 작업이 완료될 때 까지 기다리게 되지만 제어권을 넘기게 되므로 thread 자체가 중단되지는 않는다.