asyncio 라이브러리
( 공식문서 : https://docs.python.org/3.7/library/asyncio.html )
Blocking I/O
: 호출된 함수가 자신의 작업이 완료될 때까지 제어권을 가진다. 타 함수는 대기Non-Blocking I/O
: 호출된 함수(서브루틴)이 return 후 (코루틴의 yield) 호출한 함수 (메인루틴) 에 제어권 전달, 또 다른 함수 작업 (서브루틴) 을 진행할 수 있다
asyncio 를 효과적으로 쓰려면?
내가 쓰려는 함수가 Blocking 으로 구현되어 있는지, Non-Blocking 으로 구현되어 있는지 확인해야한다. Blocking 이라면 single-thread로 실행하는 것이 빠르다
스레드와 코루틴 recap
asyncio 사용 예시
그렇다면 asyncio 로 5개의 웹페이지 html 을 크롤링하는 코드를 작성해보자
asnyc
, await
: 코루틴을 위해 for
, yield
keyword를 사용할 경우, 일반 Generator 와 구별이 힘들 수 있는데, asnyc
, await
keyword를 대신 사용하여 비동기 함수로 정의했음을 쉽게 나타낼 수 있다
메인 함수도 비동기, 서브루틴으로 실행할 함수들도 비동기식으로 구현해야한다
실행 영역에서는 asyncio 의 loop를 초기화하고, 작업의 메인루틴에 해당하는 함수를 실행시키면 끝이다
그럼 메인루틴에 해당하는 main()
를 들여다보자. 이 또한 async
keyword를 통해 비동기 방식으로 작업을 수행하는 함수로 정의된다. 스레드풀을 생성하고 스케쥴링 목록을 생성 후 ( asyncio.ensure_future()
) 결과를 반환 ( asyncio.gather()
) 받도록 하면 된다
마지막으로, 스케쥴링 목록 생성하는 부분을 좀 더 들여다보자면, 서브루틴으로서 실행할 함수 (fetch
)를 ensure_future()
의 인자로 넣어주는데 이또한 비동기식으로 정의해야한다. 서브루틴으로 호출될 함수 내에서 실제 작업할 함수를 loop.run_in_executor()
을 통해 실행시킨다
import asyncio
from urllib.request import urlopen
from concurrent.futures import ThreadPoolExecutor
import threading
# 게시판 커뮤니티
urls = ['http://daum.net', 'https://naver.com', 'http://mlbpark.donga.com/', 'https://tistory.com', 'https://wemakeprice.com/']
async def fetch(url, executor):
# 실행
res = await loop.run_in_executor(executor, urlopen, url)
# print('Thread Name :', threading.current_thread().getName(), 'Done', url)
# 결과 반환
return res.read()
async def main():
# 메인루틴
# [스레드풀 생성]
executor = ThreadPoolExecutor(max_workers=10)
# [스케쥴링 목록 생성]
futures = [ asyncio.ensure_future(fetch(url, executor)) for url in urls ]
# [결과 생성]
rst = await asyncio.gather(*futures)
print('Result : ', rst)
if __name__ == '__main__':
# [루프 초기화]
loop = asyncio.get_event_loop()
# [메인루틴 실행]
loop.run_until_complete(main())
Futures 라이브러리와 파이썬 병렬성 구현 - GIL, concurrent.futures (0) | 2022.05.12 |
---|---|
코루틴 (Coroutine) (3) - 개념, 장점, 구현 (0) | 2022.05.11 |
코루틴 (Coroutine) (2) - 병행성과 Generator (0) | 2022.05.11 |
코루틴 (Coroutine) (1) - Iterator 와 Generator (0) | 2022.05.11 |
클로저 (Closure) (2) - 클로저 개념 및 구현 (0) | 2022.05.09 |
댓글 영역