코루틴
import aiohttp
import time
import asyncio
import os
import threading
async def fetch(session,url):
#현재의 프로세스id와 쓰레드id를 출력
print(f"{os.getpid()} process | {threading.get_ident()} url : {url}")
async with session.get(url) as response:
result=await response.text()
return result
async def main():
urls=["https://google.com","https://naver.com"]*10
async with aiohttp.ClientSession() as session:
result=await asyncio.gather(*[fetch(session,url) for url in urls])
if __name__=="__main__":
start = time.time()
asyncio.run(main())
print("실행시간 :", time.time() - start,"seconds")
$ python async_thread.py
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
30716 process | 3184 url : https://google.com
30716 process | 3184 url : https://naver.com
실행시간 : 0.5672705173492432 seconds
기본적으로 하나의 프로세스와 하나의 쓰레드를 사용하여 진행된다.
멀티쓰레드
import requests
import time
import os
import threading
from concurrent.futures import ThreadPoolExecutor
def fetch(params):
session=params[0]
url=params[1]
print(f"{os.getpid()} process | {threading.get_ident()} url : {url}")
with session.get(url) as response:
return response.text
def main():
#max_workers는 최대 쓰레드 갯수
#멀티쓰레드를 사용할 경우 우선순위와 쓰레드의 공간을 만드는 자원이 소비되어 코루틴으로 비동기구현보다 느릴 수 있다.
executor=ThreadPoolExecutor(max_workers=5)
urls=["https://google.com","https://naver.com"]*10
with requests.Session() as session:
# result=[fetch(session,url) for url in urls]
params=[(session,url) for url in urls]
result=list(executor.map(fetch,params))
if __name__=="__main__":
start = time.time()
main()
print("실행시간 :", time.time() - start,"seconds")
$ python multi_thread.py
12008 process | 29332 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 28144 url : https://google.com
12008 process | 13928 url : https://naver.com
12008 process | 30116 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 13928 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 12032 url : https://google.com
12008 process | 29332 url : https://naver.com
12008 process | 28144 url : https://google.com
12008 process | 30116 url : https://naver.com
12008 process | 29332 url : https://google.com
12008 process | 30116 url : https://naver.com
12008 process | 30116 url : https://google.com
12008 process | 13928 url : https://naver.com
12008 process | 13928 url : https://google.com
12008 process | 12032 url : https://naver.com
12008 process | 12032 url : https://google.com
12008 process | 28144 url : https://naver.com
실행시간 : 1.5067389011383057 seconds
workers에서 설정한 5개가 출력결과를 살펴보면 일치함을 알 수 있다.실행시간을 살펴보면 처음의 코루틴과 비교하면 느리다는 것을 알 수 있는데 이는 쓰레드풀의 생성 및 관리를 위한 시간이 들기때문에 느린 것이다.그리고 파이썬은 GIL로 인해 멀티쓰레드로 병렬적 처리는 불가능하기 때문에 비동기적으로 구현을 할거면 코루틴을 활용하는 것이 나아보인다.