- Book 파이썬답게 코딩하기 - 철학과 개념
- Book 파이썬답게 코딩하기 - 기본 문법
- Book 파이썬답게 코딩하기 - 동시성과 병렬성
- Book 파이썬답게 코딩하기 - Multiprocessing
- Book 파이썬답게 코딩하기 - 동시성
- Book 파이썬답게 코딩하기 - Coroutine
- Book 파이썬답게 코딩하기 - concurrent.futures
- Book 파이썬답게 코딩하기 - Asyncio
- Book 파이썬답게 코딩하기 - 그 밖의 파이썬 모듈
Asyncio
파이썬에서 정식으로 제공하는 비동기 논블록 I/O 모듈이다.
Python 3.4에 처음으로 포함되고 버전에 따라 새로운 문법, 기능들이 추가 되었다.
제너레이트 기반 코루틴, yield from
을 사용 논블록을 구현했다.
Asyncio in Python 3.4
event loop에 코루틴 작업을 등록해서 사용한다.
# generator_base.py
[0] Sleep time : 2, Complete time : 2020-01-07 10:59:56.946342
[5] Sleep time : 2, Complete time : 2020-01-07 10:59:56.946540
[9] Sleep time : 2, Complete time : 2020-01-07 10:59:56.946595
[3] Sleep time : 4, Complete time : 2020-01-07 10:59:58.947012
[8] Sleep time : 4, Complete time : 2020-01-07 10:59:58.947117
[6] Sleep time : 4, Complete time : 2020-01-07 10:59:58.947162
[1] Sleep time : 5, Complete time : 2020-01-07 10:59:59.950178
[7] Sleep time : 6, Complete time : 2020-01-07 11:00:00.948965
[2] Sleep time : 8, Complete time : 2020-01-07 11:00:02.948922
[4] Sleep time : 9, Complete time : 2020-01-07 11:00:03.949042
@asyncio.coroutine
데코레이터로 구현된 코루틴함수 print_time
을 비동기 논블록 방식 10번 실행하는 함수다.
코루틴 함수들은 I/O와 관련된 작업이나 CPU를 사용하지 않아도 되는 작업을 처리할 때는 제어권을 양보한다.
Asyncio in Python 3.5
async
, await
문법 추가
제너레이터 기반이 아닌 내부적으로 구현한 Python native 코루틴을 사용을 추가했다.async
는 @asyncio.coroutine
을 대체할 수 있고, await
는 yield from
을 대체할 수 있다.
event loop에서 native 코루틴
, 제너레이터 코루틴
은 상호 운영이 가능하지만 하나의 코루틴에서 2가지 문법을 혼용할 수는 없다.
# native_coroutine.py
# Python 3.4 or later
[1] Sleep time : 1, Complete time : 2020-01-07 11:14:50.021235
[0] Sleep time : 1, Complete time : 2020-01-07 11:14:50.021333
[4] Sleep time : 1, Complete time : 2020-01-07 11:14:50.021356
[5] Sleep time : 2, Complete time : 2020-01-07 11:14:51.026174
[9] Sleep time : 4, Complete time : 2020-01-07 11:14:53.023027
[8] Sleep time : 4, Complete time : 2020-01-07 11:14:53.023143
[3] Sleep time : 7, Complete time : 2020-01-07 11:14:56.022982
[6] Sleep time : 8, Complete time : 2020-01-07 11:14:57.026239
[7] Sleep time : 8, Complete time : 2020-01-07 11:14:57.026345
[2] Sleep time : 8, Complete time : 2020-01-07 11:14:57.026391
# async_for.py
# Python 3.5 or later
The mission of the Python Software Foundation is to promote, protect,
and advance the Python programming language, and to support and
facilitate the growth of a diverse and international community of
Python programmers.
from the Mission Statement page
awaitable
await
구문에서 사용될 수 있는 객체를 말한다.
이터레이를 반환하는 코루틴은 awaitable
하다라고 할 수 있다.
이터레이를 반화하는 native 코루틴
이라고 보면 된다.
asynchronous iterable, asynchronous iterator
비동기로 처리될 수 있는 iterable
과 iterator
이다.async for
문은 비동기적으로 처리될 수 있는 asynchronous iterable
대상으로 동작하고,
순회 결과 비동기 처리될 수 있는 asynchronous iterator
를 반환한다.
AsynchronousReader 클래스
파일명을 인자로 받아 파일을 열고 iteration
를 통해 한 줄씩 읽고 반환하는 클래스다.file_close
메서드를 통해 닫는다.async for
에서 값을 순회할 때 마다 __anext__
가 호출되며 이 메서드 반환값이 async for
문의 반환값으로 나타난다.
async for
문은 asyn
로 선언한 함수 native coroutine
에서만 사용할 수 있다.
# async_with.py
# Python 3.5 or later
The mission of the Python Software Foundation is to promote, protect,
and advance the Python programming language, and to support and
facilitate the growth of a diverse and international community of
Python programmers.
from the Mission Statement page
Asyncio in Python 3.6
Python 3.5 native coroutine
은 제약이 있었다.yield
를 사용하지 못하고 generator base coroutne
에서 await
구문을 사용하지 못한다.
Python 3.6 에서 이 제약이 사라진다.native coroutine
에서 yield
, yield form
을 사용할 수 있다.
이로 인해 native coroutine
으로 generator
를 만들 수 있다.
그리고, asynchronous comprehension
을 구현할 수 있도록 기능이 개선 되었다.
크게보 보면 asynchronous generator
, asynchronous comprehension
기능이 추가 되었다.
PEP 525 Asynchronous Generators
# async_gernerator.py
# Python 3.6 or later
# PEP 525 Asynchronous Generators: https://www.python.org/dev/peps/pep-0525
0
1
2
3
4
5
6
7
8
9
# async_comprehension.py
# Python 3.6 or later
Async Await Comprehension
Async Comprehension
Async Comprehension
[[0, 1, 2], [0, 1, 2]]
await
는 yield from
역확을 한다.asynchronous comprehension
은 native coroutine
문법만 지원한다.
Pythone 3.6 What's new asyncio를 참고하라.
개념 정리
asyncio
를 이해하는데는 event loop
, future/task
, coroutine
이 필요하다.
event loop
비동기 작업을 수행할 때 사용한다.
실행할 작업을 한번에 여러개 등록(schedule)
한 뒤 작업을 실행
, 지연
, 취소
할 수 있다.event loop
에서 하나의 작업을 실행했는데 작업 대기 시간이 필요한 경우(I/O 작업) 해당 작업을 일시 중지하고 다른 작업을 먼저 실행한다.
그리고 처음 실행한 작업의 대기 시간이 끝나면 다시 이어서 함수를 실행한다.
future
concurrents.futures
와 같은 작업을 관리하는 역할을 한다.Task
는 future
를 래핑한 것이다.Asyncio
에서 작업 관리는 Task
기반으로 객체
로 관리한다.future
는 향후 실행될 작업을 의미한다.
그래서 예약(schedule)
한다고 표현한다.
코루틴은 async def
로 정의되거나 제너레이터 기반으로 만들어진 함수다.
프레임워크와 무관하게 사용할 수 있지만 일반적으로 프레임워크 안에서 구현된 형태로 사용된다.sayncio
에서 event loop
에 coroutine
을 직접 등록, task
객체로 만들어서 등록 할 수 있다.Task
객체로 감싸게 될 경우 asyncio
나 event loop
에서 제공하는 메서드를 사용해서 coroutine
을 task
로 변경해서 등록한다.
future(task)
와 coroutine
을 혼동할 수 있다.await
구문에 future(task)
를 사용하면 future(task)
가 완료될 때까지 coroutine
을 중단한다.
반면 await
구문에 coroutine
을 사용하면 다른 coroutine
의 반환값을 기다리게 된다.
# coroutine_and_task.py
# Python 3.5 or later
<coroutine object func at 0x105e20a70>
['__await__', '__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'cr_await', 'cr_code', 'cr_frame', 'cr_origin', 'cr_running', 'send', 'throw']
Start coro
End coro
coro ret : Done
<Task pending coro=<func() running at /python/pythonic/06/coroutine_and_task_dir.py:9>>
['__await__', '__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_asyncio_future_blocking', '_callbacks', '_coro', '_exception', '_fut_waiter', '_log_destroy_pending', '_log_traceback', '_loop', '_must_cancel', '_repr_info', '_result', '_source_traceback', '_state', 'add_done_callback', 'all_tasks', 'cancel', 'cancelled', 'current_task', 'done', 'exception', 'get_loop', 'get_stack', 'print_stack', 'remove_done_callback', 'result', 'set_exception', 'set_result']
Start task
End task
task ret : Done
coro()
에서 출력된 func("coro")
값은 coroutine
객체다.task()
함수의 결과는 future
에서 사용하는 여러가지 메서드가 포홤되어 있어 이 메서드로 동작중 상태 확인 및 취소등을 할 수 있다.
속성 중 _coro
속성은 coro()
와 동일한 결과를 가진다.asyncio.ensure_future
를 이용 task
로 변환해주는 역활을 하는데 래핑시 넘겨진 coroutine
을 따로 보관한 것이다.
AbstratEventLoop.create_task() vs Asyncio.ensure_future()
AbstratEventLoop.create_task()
, Asyncio.ensure_future()
둘다 인자로 받은 coroutine
을 future
로 래핑해서 task
로 반환한다.
둘다 같은 기능이지만 용도와 기능이 다르다.
asyncio의 github 프로젝트에 이름 변경과 관련된 제안이 올라 왓고 여기서 토론이 열리게 되었다.
이 토론에서 귀로 반 로섬
이 코멘트로 각각의 용도를 설명하기도 했다.
AbstractEventLoop.create_task()
는 Python 3.4
에서 asyncio
가 파이썬에 포함될 때 함계 추가 됐다.AbstractEventLoop.create_task()
는 coroutine(코루틴)
을 객체를 만들어 주는 메스드다.ensure_future()
와 동일한 역할을 하지만,
중요한 점은 AbstractEventLoop.create_task()
는 AbstractEventLoop
안에 전의된 메드드라는 것이다.
바로 event_loop
에서 작업을 등록하기 위해 제공하는 메서드다.
비동기 로직을 구현할 때 보통 event loop
를 사용한다.
자체적으로 event loop
를 구현할 때 이 AbstractEventLoop
를 상속받아서 구현하게 한다.
그리고, 구현한 event loop
에 작업을 등록할 때 create_task
를 사용하게 된다.
즉, event loop
특성에 맞는 작업을 생성하기 위해 AbstractEventLoop.create_task()
를 사용한다.
반면 asyncio.ensure_func()
는 asyncio
모듈에 정의되어 있는 메서드다.asyncio.asyncio
라는 이름이 Python 3.5
버전에서 asyncio.ensure_func()
로 변경됐다.
즉, asyncio
모듈에서 사용하는 task
를 만들고 이 task
의 실행을 등록(예약)하기 위한 메서드다.
asyncio
모듈에 있는 event loop
를 사용하다면 asyncio.ensure_func()
를 사용해서 작업 관리를 하면 된다.
별도 커스트마이징한 event loop
를 사용하면 event loop
에서 제공하는 create_task
를 사용하면 된다.
기능차이는 AbstractEventLoop.create_task()
는 coroutine
을 받는다.asyncio.ensure_func()
는 coroutine
, future object
, task object
를 입력 받을 수 있다.coroutine
을 받으면 future
로 래핑한 task
를 반환하고, future
, task
객체를 받으면 그대로 반환한다.Python 3.5
에서 awaitable
한 객체도 받을 수 있도록 기능이 추가됐다.
Python 3.7
에서 asyncio.create_task
객체가 추가 됐다.AbstractEventLoop.create_task()
와 유사하고 task
를 반환하지만, 작업을 등록(예약)하지는 않고, 순수하게 task
를 만들기만 한다.
# native_couroutine_with_task.py
# Python 3.5 or later
[0] task is cancelled
[2] task is cancelled
[4] task is cancelled
[6] task is cancelled
[8] task is cancelled
[1] Sleep time : 1, Complete time : 2020-01-08 11:57:27.732474
[1] Call callback function
[5] Sleep time : 2, Complete time : 2020-01-08 11:57:28.734988
[5] Call callback function
[7] Sleep time : 3, Complete time : 2020-01-08 11:57:29.734890
[9] Sleep time : 3, Complete time : 2020-01-08 11:57:29.735020
[7] Call callback function
[9] Call callback function
[3] Sleep time : 4, Complete time : 2020-01-08 11:57:30.735668
[3] Call callback function
'lang > py' 카테고리의 다른 글
Book 파이썬답게 코딩하기 - 그 밖의 파이썬 모듈 (0) | 2020.01.27 |
---|---|
Book 파이썬답게 코딩하기 - concurrent.futures (0) | 2020.01.21 |
Book 파이썬답게 코딩하기 - Coroutine (0) | 2020.01.20 |
Book 파이썬답게 코딩하기 - 동시성 (0) | 2020.01.16 |
Book 파이썬답게 코딩하기 - Multiprocessing (0) | 2020.01.14 |