[Python] Asyncio 맛보기

Sireal·2022년 4월 11일
0

Python

목록 보기
14/14

비동기 프로그래밍(이벤트 콜백 등으로 돌아가는 프로그래밍)을 사용하기 위해서 asyncio 라는 친구를 사용할 수 있다.
asyncio에서는 코루틴 이라는 유사 멀티쓰레드 프로그래밍 방식을 사용한다.

코루틴(Coroutine)에 대해 들어봤을까?

단일 쓰레드에서 멀티태스킹을 구현하는 기술 중 하나이다.
일종의 태스크이며, 루틴이다. 그냥 여러 태스크들이 이 루틴하나에서 서로 방해하나 없이 차례로 같이 움직이는 거다.

  • 여러태스크끼리 값을 쉽게 주고받을수도 있게 된다.

내가 지금 하는 펌웨어, 임베디드에서는 코드 가독성문제 등 유지보수 때문에 사용하면 안되는 개념인데,
웹서버나 모바일앱 등에서는 많이 쓰이는 개념이다. (펌웨어빼고 다사용한다는 뜻)

극한의 효율이라는 장점이 있어서 파이썬3에서 지원되는 개념이다.

asyncio을 이용하여 코루틴을 구현하기전에,
코루틴과는 관련이 없는 파이썬3의 iterator, yield 를 알아야한다.

  • coroutine을 위해 생성되는 event를 처리하는 함수를 사용해야하는데,
    이벤트가 발생하면 그 순서대로 처리해야해서 파이썬에서 지원하는 순서대로 처리하는 문법들을 알아는것.

Iterator

Iterator 뜻은 반복자.
__iter__(), __next()__ 메소드를 가진 객체(클래스)를 말한다.

__iter__() 메소드를 이용해서 iterator를 얻고, __next__() 메소드를 이용해서 반복해서 값을 던는 것.

  • __iter__() : iterator 오브젝트 객체를 리턴
  • __next()__ : 호출될 때마다 다음 값을 리턴

iter를 이용해서 반복 함수를 만들고,
next를 통해서 차례로 다음값을 리턴하게하는 함수를 만든다.
이정도만 알면된다.

Yield

생산하다 라는 뜻.
yield 키워드는 iterator를 편하게 사용하게 도와주는 키워드.
generator 라고 불림.

#  iter 함수 
def callee():
    yield 1
    yield 2
		
x = callee()
i = next(x) # 반복가능한 iter가 들어간 next()
i = next(x)
  • next()로 순서대로 값을 차례로 보여줌.
  • Caller인 i가 callee를 호출할때 마다 yiled를 통해 차례로 1, 2를 넘겨줌.
  • yeild를 사용하지 않으면 Iteraotr로 복잡하게 코드를 구현해야함. 그래서 yeild 를 이용해서 내가 원하는 값을 차례로 넘기자.

Asyncio

Async 가 비동기라는 뜻.
event loop 방식의 비동기 프로그래밍이 가능한 파이썬 표준 라이브러리이다.

C언어에서 많이 사용하던 event loop방식과 매우 유사하다.

async, await

파이썬 3.5부터 지원되는 async와 yield를 대체하는 키워드
뭐만하면 대체되네

async 키워드가 들어간함수에서는 yield, yield from은 사용할수 없고,
await를 사용한다!
그리고 coroutine이 된다.

import types

@types.coroutine
def switch():
    yield

async def coro1():
    print('C1: Start')
    await switch()
    print('C1: a')
    await switch()
    print('C1: b')
    await switch()
    print('C1: end')

async def coro2():
    print('C2: Start')
    await switch()
    print('C2: a')
    await switch()
    print('C2: b')
    await switch()
    print('C2: end')

def run(coros):
    coros = list(coros)

    while coros:
        for coro in list(coros):
            try:
                coro.send(None)
            except StopIteration:
                coros.remove(coro)

c1 = coro1()
c2 = coro2()
run([c1, c2])
  • yield없이 await키워드를 이용하여 task switching을 구현했다.
profile
🚄계속 앞으로🚄

0개의 댓글