asyncio(Asynchronous I/O는 비동기 프로그래밍을 위한 모듈이며 CUP 작업과 I/O를 병렬로 처리하게 해줌
동기(synchronous) 처리는 특정 작업이 끝나면 다음 작업을 처리하는 순차처리 방식이고,
비동기(asynchronous) 처리는 여러 작업을 처리하도록 예약한 뒤 작업이 끝나면 결과를 얻는 방식입니다.
1. asyncio 사용하기
네이트브 코루틴 만들기
파이썬에서는 제너레이터 기반의 코루틴과 구분하기 위해 async def로 만든 코루틴은 네이티브 코루틴이라고 합니다.
async def 키워드는 파이썬 3.6 이상부터 사용 가능
import asyncio
async def hello(): # async def로 네이티브 코루틴 생성
print("Hello world!")
loop = asyncio.get_event_loop() # 이밴트 루프를 얻고
loop.run_until_complete(hello()) # hello가 끝날때 까지 기다림
loop.close() # 이벤트 루프 닫음
해석 :
run_run_until_complete는 네이티브 코루틴이 이벤트 루프에서 실행되도록 예약하고 해당 네이티브 코루틴이 끝날 때 까지 기다림.
이벤트 루푸를 통해서 hello 코루틴이 실행됨
할 일이 끝났으면 close로 종료
await로 네이트브 코루틴 실행하기
await 뒤에 코루틴 객체,퓨처 객체, 태스크 객체를 지정하면 해당 객체가 끝날 때까지 기다린 뒤 결과를 반환합니다.
awiait는 네이티브 코루틴에서만 사용 가능 합니다.
import asyncio
async def add(a,b):
print("add: {0} + {1}".format(a,b))
await asyncio.sleep(1.0) # 1초대기
return a+b # 두 수를 더한값 출력
async def print_add(a,b):
result = await add(a,b) # await로 다른 네이티브 코루틴 실행 후 반환값 저장
print("print_add: {0} + {1} = {2}".format(a,b,result))
loop = asyncio.get_event_loop() # 이벤트 루프를 얻음
loop.run_until_complete(print_add(1,2)) # 실행
loop.close() # 이벤트 루프 반납
비동기로 웹사이트 가져오기
일반 적으로 사용 웹페이지 가져오기
from time import time
from urllib.request import Request, urlopen
urls = ["http://www.google.co.kr/search?q=" + i for i in ["apple","pear","grape","pineapple","orange","strowberry"]]
begin = time()
result = []
for url in urls:
request = Request(url,headers={"User-Agent":"Mozilla/5.0"})
respone = urlopen(request)
page = respone.read()
result.append(len(page))
print(result)
end = time()
print("실행 시간 {0:3f}초".format(end-begin))
비동기로 웹페이지 가져오기 코드
from time import time
from urllib.request import Request, urlopen
import asyncio
urls = ['https://www.google.co.kr/search?q=' + i
for i in ['apple', 'pear', 'grape', 'pineapple', 'orange', 'strawberry']]
async def fetch(url):
request = Request(url, headers={'User-Agent': 'Mozilla/5.0'}) # UA가 없으면 403 에러 발생
response = await loop.run_in_executor(None, urlopen, request) # run_in_executor 사용
page = await loop.run_in_executor(None, response.read) # run in executor 사용
return len(page)
async def main():
futures = [asyncio.ensure_future(fetch(url)) for url in urls]
# 태스크(퓨처) 객체를 리스트로 만듦
result = await asyncio.gather(*futures) # 결과를 한꺼번에 가져옴
print(result)
begin = time()
loop = asyncio.get_event_loop() # 이벤트 루프를 얻음
loop.run_until_complete(main()) # main이 끝날 때까지 기다림
loop.close() # 이벤트 루프를 닫음
end = time()
print('실행 시간: {0:.3f}초'.format(end - begin))
async def fetch(url):
request = Request(url, headers={'User-Agent': 'Mozilla/5.0'}) # UA가 없으면 403 에러 발생
response = await loop.run_in_executor(None, urlopen, request) # run_in_executor 사용
page = await loop.run_in_executor(None, response.read) # run in executor 사용
return len(page)
1. urlopen이나 reponse.read 같은 함수(메서드)는 결과가 나올 때까지 코드 실행이 중단(block)이 되는데 이런 함수들을
블로킹 I/O(blocking I/O) 함수라고 부름
2. 코루틴 안에서 블로킹 I/O 함수를 실행하려면 이벤트 루프의 run_in_executor 함수를 사용하여 다른 스레드에서
병렬로 실행시켜야 함
3. run_in_executor의 첫 번째 인수는 executor인데 함수를 실행시켜줄 스레드 풀 또는 프레세스 풀임
이벤트루프.run_in_excutor(None,함수,인자1,인자2)
4. run_in_executor도 코루틴이므로 await로 실행한 뒤 결과를 갸져옴
async def main():
futures = [asyncio.ensure_future(fetch(url)) for url in urls]
# 태스크(퓨처) 객체를 리스트로 만듦
result = await asyncio.gather(*futures) # 결과를 한꺼번에 가져옴
print(result)
1. main에서는 코루틴 여러 개를 동시에 실행하는데 이때는 먼저 asyncio.ensure_future 함수를 사용하여 태스크
객체를 생성하고 리스트로 만들어줌
태스크객체 = asyncio.ensure_future(코루틴객체 또는 퓨처객체)
2. asyncio.gather는 모든 코루틴 객체(퓨처,태스크 객체)가 끝날 때가지 기다린 뒤 결과를 리스트로 반환
변수 = await asyncio.gather(코루틴객체1,코루틴객체2)
'Python' 카테고리의 다른 글
[Python] 크롤링-starbucks 음류수 종류 - csv (0) | 2020.07.03 |
---|---|
[Python] 크롤링-billboard 차트 - csv (0) | 2020.07.02 |
[Python] coroutine (코루틴) (1) | 2020.06.29 |
[Python] Multiprocessing (2) | 2020.06.29 |
[Python] Thread (0) | 2020.06.29 |
댓글