본문 바로가기

Python

Asyncio, coroutine

#coroutine
sub-routine: 종속되어있는 루틴. 함수도 서브 루틴에 포함된다.
co-roution: 협력적으로 실행되는 루틴. 비동기 실행에서 사용된다. 실행중인 함수를 잠시 멈추고 나중에 실행을 재생할 수 있다.

# 서브루틴 예시
def func(a):
    return a+1
a=1
b=func(a)
print(b)

서브루틴은 결국 순차적으로 처리되는 것이나 다름없다.(동기처리)

반대로 비동기 프로그래밍은 여러 작업을 동시에 처리할 수 있다.

코루틴 Vs. 멀티 스레딩

  • 스레드는 운영체제에 의해 관리되면서 여러 작업을 수행하며 각 스레드는 메모리상에서 자체 스택을 가지고 있어서 독립적인 흐름을 가진다.
    멀티 프로세싱에 비해 오버헤드가 적고 자원 공유가 쉽지만 공유하는 자원으로 인해 동기화 문제를 고려해야한다.
  • 코루틴은 언어차원에서 제공되는 기능이며 코루틴 객체를 스위칭하는 것을 통해 비동기 작업의 동시성(concurrency)를 구현할 수 있다. 코루틴은 스레드보다 더 가볍고, 빠르며, 동기화 문제가 발생하지 않고, 스위칭 시점을 프로그래머가 직접 지정할 수 있으나, 하나의 스레드 상에서 실행하는것이 권장된다.

병렬성은 멀티 스레딩으로 얻어야하며 코루틴은 스레드의 대안이 아닌, 스레드를 더 쪼개 쓰기위한 방법이라고 할 수 있다.

스레드는 I/O-bound작업(CPU연산 보다 입출력으로 인한 대기시간이 더 긴 작업) 및 병렬처리, 코루틴은 I/O-bound작업 및 비동기 이벤트 처리에 사용한다.

파이썬 코루틴

파이썬이 기본적으로 제공하는 코루틴 기능으로, 일반적인 함수와 유사하지만 실행중인 함수를 일시중지 하고 나중에 다시 시작할 수 있는 기능

핵심키워드 설명
yield 만날때 마다 함수를 일시중단 후 반환할 값이 있다면 값을 반환한다.
next 다음 yield를 만날때까지 코루틴을 다시 시작
send 코루틴에 값 전달해 다시실행. yield 반환값이 send함수의 인자가 된다.
def my_coroutine():
    while True:
        value = yield # send 로부터 값 받음
        print("Received value:", value)


# 코루틴 객체 생성

co = my_coroutine()

# 코루틴 실행 준비 - 첫 yield 전까지 실행

next(co)

# 값을 보내기

co.send("Hello, world!") # Received value: Hello, world!  
co.send("hi, world!") # Received value: hi, world!  
co.send("bye, world!") # Received value: bye, world!

def my_generator():  
yield 1 # yield로 반환  
yield 2  
yield 3

gen = my_generator()  
print(next(gen)) # 1  
print(next(gen)) # 2  
print(next(gen)) # 3

Q:iterable 하면 next()를 쓸수 있다고 알고 있습니다. 코루틴은 iterable한 객체 인건가요?

A: 맞습니다. 위 예시코드의 2번째 형식의 coroutine객체는 제너레이터라고도 불리며 for문에도 사용가능한 iterable한 객체입니다.

def my_generator():
    yield 1
    yield 2
    yield 3

gen = my_generator()
for i in gen:
    print("in for",i) # in for 1,in for 2, in for 3

Asynco

비동기 프로그래밍을 위한 라이브러리fh, 상태를 자동 관리하여 편리하고 안전하게 동시성을 구현할 수 있다.

키워드 설명
async 코루틴 선언
await 코루틴 안에서 다른 코루틴의 실행완료를 기다림 - 꼭 그 작업이 끝나야 실행이 가능할 때
run() 코루틴을 시작한다.
## 예시 코드
```python
import asyncio
import random

async def fetch_data():
print("데이터를 가져오는 중...")
await asyncio.sleep(1) # 데이터를 가져오는데 1초가 걸린다고 가정
return random.randint(1, 100)

동시에 실행될 필요가 있지만

결국 코루틴의 결과가 필요한경우

async def main():
data = await fetch_data()
print(f"가져온 데이터: {data}")

실행 시작

asyncio.run(main())

```

레퍼런스

https://velog.io/@haero_kim/Thread-vs-Coroutine-%EB%B9%84%EA%B5%90%ED%95%B4%EB%B3%B4%EA%B8%B0
https://sogummi.tistory.com/99

'Python' 카테고리의 다른 글

재귀 & 추상클래스  (0) 2023.05.01
객체지향 프로그래밍  (0) 2023.05.01
파이썬 패키지 관리  (0) 2023.04.26
프로세스,스레드,멀티프로세싱, 멀티 스레딩  (0) 2023.04.25
각 타입별 중요 메소드  (0) 2023.04.24